게시판 6

JIWOO YUN·2024년 4월 22일
0

게시판만들기

목록 보기
6/21
post-custom-banner

Spring Security 추가

  • spring에서 제공하는 보안 기능
  • 강력하고 사용자 정의 가능한 인증 및 액세스 제어 프레임워크
  • Spring Security

gradle에 spring security 추가

implementation 'org.springframework.boot:spring-boot-starter-security'
  • spring security를 적용하게 되면 기본적으로 인증되지 않은 사용자가 서비를 사용할 수 없도록 막아버리기 때문에 Security설정 파일을 추가해서 설정해줘야한다.
@Configuration
@EnableWebSecurity
public class SecurityConfig {


    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.
                authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
                        .requestMatchers(new AntPathRequestMatcher("/**")).permitAll());

        return http.build();
    }
}
  • @EnableWebSecurity
    • 이 애너테이션을 추가하면 SecurityFilterChain을 노출하여 WebSecurityConfigurer에서 Spring Security 구성이 정의 되도록 할 수 있다고 한다.
    • 모든 요청 url이 스프링 시큐리티의 제어를 받도록 만들어 준다.
    • EnableWebSecurity (spring-security-docs 6.2.4 API)
  • 세부 설정은 SecurityFilterChain 빈을 생성하여 설정 가능
    • 로그인을 하지않더라고 모든 페이지에 접근 할 수 있도록 추가해준다.

전에는 H2-console에 문제가 있었다고 하는데 현재 내가 사용할 경우에 h2 -console의 경로가 /h2-console을 포함하고 있지않아서 위의 허용범위에 포함되어 제대로 작동하고 있다.

  • 왜 경로가 /h2-console이 아닐까 라는 생각에 찾아봤지만 명확한 결과가 없어서 이 부분은 잘 이해가 되지 않지만 이렇다고 일단 넘어가고 있다.

Spring Security를 적용하였으니 사용하기 위해서 회원가입 기능을 추가하자.

  • 회원가입을 할때 필요한게 뭐가 있을까?

    • 아이디
    • 비밀번호
    • 비밀번호확인
    • 이메일

정도가 있을거 같다.

  1. 회원 엔티티를 만들고 회원 저장소 및 서비스를 생성을 해준다.
  2. 회원 가입 폼을 만들어준다.
  3. 회원 가입 컨트롤러를 통해서 가입 진행.

회원 엔티티

@Getter
@Setter
@Entity
public class SiteUser {


    @Id
    @Column(name = "user_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String username;

    private String password;

    @Column(unique = true)
    private String email;
}

username과 email에 unique를 주는 이유

  • 값이 중복되지 않게 하기 위해서
  • 동일한 값이 들어오게되면 관리하기 어려워짐
    • 사실 이 경우에는 뒤에 a 같은 문자를 붙이는 경우가 많다.
    • 동명이인인 사람이 가입하는 경우가 없지 않기 때문에 현재는 게시판 연습이기 때문에 unique로 중복값이 못들어가게 막아둔다.

userRepository 생성 및 서비스 생성

@RequiredArgsConstructor
@Service
public class UserService {

    private final UserRepository userRepository;

    public SiteUser create(String username,String email,String password){
        SiteUser user = new SiteUser();
        user.setUsername(username);
        user.setEmail(email);
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        user.setPassword(passwordEncoder.encode(password));
        userRepository.save(user);

        return user;
    }
}
  • service에서 create의 경우 비밀번호 관리가 중요하다.
    • 비밀번호의 경우 노출되면 안되는 중요한 데이터로서 암호화를 통해서 관리해줘야한다.
    • BcyptPasswordEncoder 클래스를 통해서 encode하여 비밀번호를 암호화해서 저장하고 검증하는 게 필요하다.
      • BcyptPasswordEncoder의 경우 bean등록을 해두고 사용하는게 좋다
        • 만약 암호화 방식의 변경하게 되면 BcyptPasswordEncoder를 사용한 모든 프로그램을 다찾아서 수정해야하기 때문이다.

BcyptPasswordEncoder 빈 등록 진행

UserCreateForm 추가

@Getter
@Setter
public class UserCreateForm {

    @Size(min = 3, max = 25)
    @NotEmpty(message = "사용자 ID는 필수 입니다.")
    private String username;

    @NotEmpty(message = "비밀번호는 필수 항목입니다.")
    private String password1;

    @NotEmpty(message = "비밀번호 확인은 필수 항목입니다.")
    private String password2;

    @NotEmpty(message = "이메일은 필수 항목입니다.")
    @Email
    private String email;
}

UserController 추가

@RequiredArgsConstructor
@Controller
@RequestMapping("/user")
public class UserController {

    private final UserService userService;

    @GetMapping("/signup")
    public String signup(UserCreateForm userCreateForm){
        return "signup_form";
    }

    @PostMapping("/signup")
    public String signup(@Valid UserCreateForm userCreateForm,
                         BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return "signup_form";
        }

        if(!userCreateForm.getPassword1().equals(userCreateForm.getPassword2())){
            bindingResult.rejectValue("password2","passwordIncorrect",
                    "2개의 패스워드가 일치하지 않습니다.");
            return "signup_form";
        }

        userService.create(userCreateForm.getUsername(),userCreateForm.getEmail(),userCreateForm.getPassword1());

        return "redirect:/";
    }
}
  • 회원가입시에 패스워드 와 패스워드 확인이 다를 경우 error가 맞기 때문에 rejectError를 추가

UserController 에 예외처리 추가

        try {
            userService.create(userCreateForm.getUsername(), userCreateForm.getEmail(), userCreateForm.getPassword1());
        } catch (DataIntegrityViolationException e) {
            log.error("중복 회원가입 진행 오류");
            bindingResult.reject("signupFailed", "이미 등록된 사용자입니다.");

            return "signup_form";
        } catch (Exception e) {
            e.printStackTrace();
            bindingResult.reject("signupFailed", e.getMessage());
            return "signup_form";
        }

중복 id 또는 이메일로 회원가입시도시 애초에 불가능하게 unique를 걸어놨기 때문에 500 에러가 발생한다.

  • 이러면 사용자 입장에서 에러페이지를 보게되어 사용자 경험적으로 좋지 않아서 예외를 추가로 적용하여 signup_form을 다시 보여주는게 가장 좋다.
profile
열심히하자
post-custom-banner

0개의 댓글