Spring Boot를 이용하여 Login까지 간단히 끝냄. Maven버전이 아닌 Gradle 버전으로 남김

1. 새로운 프로젝트 생성
   - Type : Gradle 로 선택(필수)

2. Next 버튼 누른 후 Dependency 설정
   - 이전에 사용했던 항목이 있으면 Frequently Used 로 바로 보임. 체크를 하면 됨
   - 없으면 왼쪽 하단 부분에서 찾아(세모 클릭하면 펼쳐짐) 체크
   - 선택된 dependencies는 오른쪽 하단에 Selected 로 표시 됨

 

3.프로젝트 구조
   - 파일 위치 및 파일명 참조

4. Build.gradle 확인
   - dependencies 에서 implementation은 선택한 항목-
   - commons-beanutils 를 추가함.

-- jquery, bootstrap 추가

https://www.webjars.org/ 에서 해당 버전에 맞게 찾아옴
   - Build Tool 에서 해당 Tool 선택
   - 사용할 jar 의 추가방법 복사 : compile 'org.webjars:jquery:3.4.1'

-- 추가한 build.gradle

5. DB 연결 : src/main/resources 아래에 application.properties
   - server 포트 변경할 때 사용. 기본값은 8080이므로 변경할 때만 추가
   - mysql 설정에 localhost:3306 뒤에 연결할 db명을 적고 username, password
   - JPA를 사용하므로 hibernate.dll-auto=create 으로 추가

6. db script
  - mysql 을 사용하는 경우 id column에 PK, Auto_increment 속성을 넣는다.
  - oracle을 사용하는 경우에는 auto_increment 는 필요없다(별도의 sequence 사용)

   - key 정보를 잘못 설정한 경우 : table 생성 후 auto_increment 를 추가하려고 하면 foreign key가 있다고 오류남
     Key 삭제 후 다시 만들어야 함. table drop 이후에는... 애매해 짐

# unique key 삭제 및 생성
drop index 유니크키명 on 테이블명;
create unique index  유니크키명 on 테이블명 (컬럼명, 컬럼명);


# type이 innodb일 경우에는 unique key 삭제 하기전에 foreign key를 삭제해야 한다.
alter table 테이블명 drop foreign key 포린키명;
drop index 유니크키명 on 테이블명;


# innodb 타입 foreing key 재생성
alter table 테이블명 add CONSTRAINT 포린키명  foreign key (컬럼명) references 디비명 (컬럼명) on delete cascade;7. 미리보기
   - build.gradle에서 bootstrap, jquery를 추가하지 않은 경우
   - 개발자 모드로 확인시 script 오류가 확인 됨.

   - 추가 후

 

source

- UserRegistrationDto : package com.nobang.sample.web.dto

import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;

import com.nobang.sample.constraint.FieldMatch;



@FieldMatch.List({
    @FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match"),
    @FieldMatch(first = "email", second = "confirmEmail", message = "The email fields must match")
})
public class UserRegistrationDto {

    @NotEmpty
    private String firstName;

    @NotEmpty
    private String lastName;

    @NotEmpty
    private String password;

    @NotEmpty
    private String confirmPassword;

    @Email
    @NotEmpty
    private String email;

    @Email
    @NotEmpty
    private String confirmEmail;

    @AssertTrue
    private Boolean terms;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getConfirmPassword() {
        return confirmPassword;
    }

    public void setConfirmPassword(String confirmPassword) {
        this.confirmPassword = confirmPassword;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getConfirmEmail() {
        return confirmEmail;
    }

    public void setConfirmEmail(String confirmEmail) {
        this.confirmEmail = confirmEmail;
    }

    public Boolean getTerms() {
        return terms;
    }

    public void setTerms(Boolean terms) {
        this.terms = terms;
    }
}

 

- SampleUser : package com.nobang.sample.model

import javax.persistence.*;
import java.util.Collection;

@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = "email"))
public class SampleUser {

    @Id
//    @GeneratedValue(strategy = GenerationType.AUTO) // ORACLE
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;
    private String lastName;
    private String email;
    private String password;

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(
        name = "sample_users_roles",
        joinColumns = @JoinColumn(
            name = "user_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(
            name = "role_id", referencedColumnName = "id"))
    private Collection < SampleRole > roles;

    public SampleUser() {}

    public SampleUser(String firstName, String lastName, String email, String password) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.password = password;
    }

    public SampleUser(String firstName, String lastName, String email, String password, Collection < SampleRole > roles) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.password = password;
        this.roles = roles;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Collection < SampleRole > getRoles() {
        return roles;
    }

    public void setRoles(Collection < SampleRole > roles) {
        this.roles = roles;
    }

    @Override
    public String toString() {
        return "User{" +
            "id=" + id +
            ", firstName='" + firstName + '\'' +
            ", lastName='" + lastName + '\'' +
            ", email='" + email + '\'' +
            ", password='" + "*********" + '\'' +
            ", roles=" + roles +
            '}';
    }
}

 

- SampleRole : package com.nobang.sample.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class SampleRole {

    @Id
//    @GeneratedValue(strategy = GenerationType.AUTO) // ORACLE
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    public SampleRole() {}

    public SampleRole(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Role{" +
            "id=" + id +
            ", name='" + name + '\'' +
            '}';
    }
}

 

- UserRepository : package com.nobang.sample.repository;

@Repository
public interface UserRepository extends JpaRepository < SampleUser, Long > {
    SampleUser findByEmail(String email);
}

참고 : JPA에서 기본으로 제공하는 method

- FieldMatch : package com.nobang.sample.constraint;

import javax.validation.Payload;
import javax.validation.Constraint;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({
    TYPE,
    ANNOTATION_TYPE
})
@Retention(RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
@Documented
public @interface FieldMatch {
//    String message() default "{constraints.field-match}";
//    Class << ? > [] groups() default {};
//    Class << ? extends Payload > [] payload() default {};
    
    String message() default "{constraints.fieldmatch}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};    
    
    String first();
    String second();

    @Target({
        TYPE,
        ANNOTATION_TYPE
    })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        FieldMatch[] value();
    }
}

 

- FieldMatchValidator : package com.nobang.sample.constraint;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.apache.commons.beanutils.BeanUtils;

public class FieldMatchValidator implements ConstraintValidator < FieldMatch, Object > {

    private String firstFieldName;
    private String secondFieldName;

    @Override
    public void initialize(final FieldMatch constraintAnnotation) {
        firstFieldName = constraintAnnotation.first();
        secondFieldName = constraintAnnotation.second();
    }

    @Override
    public boolean isValid(final Object value, final ConstraintValidatorContext context) {
        try {
            final Object firstObj = BeanUtils.getProperty(value, firstFieldName);
            final Object secondObj = BeanUtils.getProperty(value, secondFieldName);
            return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
        } catch (final Exception ignore) {}
        return true;
    }
}

 

- UserService : package com.nobang.sample.service;

import org.springframework.security.core.userdetails.UserDetailsService;

import com.nobang.sample.model.SampleUser;
import com.nobang.sample.web.dto.UserRegistrationDto;


public interface UserService extends UserDetailsService {

    SampleUser findByEmail(String email);

    SampleUser save(UserRegistrationDto registration);
}

- UserServiceImpl : package com.nobang.sample.service;

import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import com.nobang.sample.model.SampleRole;
import com.nobang.sample.model.SampleUser;
import com.nobang.sample.repository.UserRepository;
import com.nobang.sample.web.dto.UserRegistrationDto;



@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    public SampleUser findByEmail(String email) {
        return userRepository.findByEmail(email);
    }

    public SampleUser save(UserRegistrationDto registration) {
        SampleUser user = new SampleUser();
        user.setFirstName(registration.getFirstName());
        user.setLastName(registration.getLastName());
        user.setEmail(registration.getEmail());
        user.setPassword(passwordEncoder.encode(registration.getPassword()));
        user.setRoles(Arrays.asList(new SampleRole("ROLE_USER")));
        return userRepository.save(user);
    }

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        SampleUser user = userRepository.findByEmail(email);
        if (user == null) {
            throw new UsernameNotFoundException("Invalid username or password.");
        }
        return new org.springframework.security.core.userdetails.User(user.getEmail(),
            user.getPassword(),
            mapRolesToAuthorities(user.getRoles()));
    }

//    private Collection << ? extends GrantedAuthority > mapRolesToAuthorities(Collection < Role > roles) {
//        return roles.stream()
//            .map(role - > new SimpleGrantedAuthority(role.getName()))
//            .collect(Collectors.toList());
//    }
    
    private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection roles){
        return roles.stream()
                .map(role -> new SimpleGrantedAuthority(role.getName()))
                .collect(Collectors.toList());
    }
}

 

- SecurityConfiguration : package com.nobang.sample.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.nobang.sample.service.UserService;

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers(
                "/registration**",
                "/js/**",
                "/css/**",
                "/img/**",
                "/webjars/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .logout()
            .invalidateHttpSession(true)
            .clearAuthentication(true)
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/login?logout")
            .permitAll();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
        auth.setUserDetailsService(userService);
        auth.setPasswordEncoder(passwordEncoder());
        return auth;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }
}

 

- MainController : package com.nobang.sample.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MainController {

    @GetMapping("/")
    public String root() {
        return "index";
    }

    @GetMapping("/login")
    public String login(Model model) {
        return "login";
    }

    @GetMapping("/user")
    public String userIndex() {
        return "user/index";
    }
}

 

- UserRegistrationController :

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.nobang.sample.model.SampleUser;
import com.nobang.sample.service.UserService;
import com.nobang.sample.web.dto.UserRegistrationDto;



@Controller
@RequestMapping("/registration")
public class UserRegistrationController {

    @Autowired
    private UserService userService;

    @ModelAttribute("user")
    public UserRegistrationDto userRegistrationDto() {
        return new UserRegistrationDto();
    }

    @GetMapping
    public String showRegistrationForm(Model model) {
        return "registration";
    }

    @PostMapping
    public String registerUserAccount(@ModelAttribute("user") @Valid UserRegistrationDto userDto,
        BindingResult result) {

        SampleUser existing = userService.findByEmail(userDto.getEmail());
        if (existing != null) {
            result.rejectValue("email", null, "There is already an account registered with that email");
        }

        if (result.hasErrors()) {
            return "registration";
        }

        userService.save(userDto);
        return "redirect:/registration?success";
    }
}

 

참조 : https://www.javaguides.net/2019/02/spring-mvc-5-spring-security-5-hibernate-5-mysql.html

728x90
BLOG main image
"그게 뭐 어쨌다는 거냐?" 늘 누가 나에게 나에대한 말을할 때면 이말을 기억해라. by nobang

카테고리

nobang이야기 (1933)
Life With Gopro (7)
Life With Mini (79)
Diary (971)
너 그거 아니(do you know) (162)
난 그래 (159)
Study (290)
속지말자 (10)
Project (34)
Poem (15)
Song (0)
Photo (113)
낙서장 (45)
일정 (0)
C.A.P.i (2)
PodCast (0)
nobang (27)
고한친구들 (4)
recieve (0)
History (0)
android_app (2)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

Total :
Today : Yesterday :