6. 스프링 인증블로그v1 (2)회원가입

gov's avatar
Nov 28, 2024
6. 스프링 인증블로그v1 (2)회원가입
💡
Spring Security 필터 체인(Filter Chain) 적용 -기존 필터 삭제 Spring Security에서 HTTP 요청을 처리할 때 적용되는 여러 개의 보안 필터들의 순차적 집합.보안 필터들이 요청을 처리하는 순서를 정의, 이를 통해 보안 관련 작업을 효율적 처리 가능
 

0. FilterSecurity Filter 차이

기준
Spring Boot Filter
Spring Security Filter
목적
요청/응답의 일반적인 처리
요청/응답의 일반적인 처리
동작 시점
애플리케이션 전반
보안 관련 요청 처리 시
적용 범위
특정 URL, 전역 또는 특정 요청 처리
보안 컨텍스트 내에서만 적용
구현 방식
Filter 인터페이스 구현
Security Filter Chain 구성
 

1. SecurityConfig 클래스 생성

Spring Security를 설정하여 애플리케이션 보안 설정, 인증 및 권한 부여 방법을 정의
/s/** 경로는 인증된 사용자만 접근 가능
@Configuration public class SecurityConfig { // user가 입력한 비밀번호와 DB비밀번호와 맞는지 확인 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SecurityFilterChain configure(HttpSecurity http) throws Exception { http.authorizeHttpRequests(r-> r.requestMatchers("/s/**").authenticated().anyRequest().permitAll()) .formLogin(f->f.loginPage("/login-form") .loginProcessingUrl("/login") .defaultSuccessUrl("/")); return http.build(); } }
 

2. 인증된 사용자 정보 저장

UserDetails는 Spring Security에서 인증된 사용자의 정보를 저장 및 제공하는 인터페이스. 인증을 위한 필수 메서드를 정의함
public class User implements UserDetails { @Override public Collection<? extends GrantedAuthority> getAuthorities() { // 사용자 권한 반환 return List.of(); } @Override public boolean isAccountNonExpired() { // 계정 유효 기간 확인 return true; } @Override public boolean isAccountNonLocked() { // 계정 잠김 확인 return true; } @Override public boolean isCredentialsNonExpired() { // 인증 자격 증명(ex.일정 기간마다 비밀번호 변경 요청) return true; } @Override public boolean isEnabled() { // 계정 활성화 상태 확인(또는 비활성화 설정) return true; // true -조건이 만족됨 } }
 

3. 회원가입 기능 구현

  1. UserSevice회원가입 메서드
    1. @RequiredArgsConstructor @Service public class UserSevice implements UserDetailsService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; @Transactional public void 회원가입(UserRequest.JoinDTO joinDTO) { userRepository.save(joinDTO.toEntity(passwordEncoder)); } // POST 요청 // /login 호출됨 // key 값 -> username, password // Content-Type -> x-www-form-urlencoded // username을 받아 사용자 조회 @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username); return user; // User에 반환값 받기 } }
  1. UserRequest JoinDTO → 회원가입시 입력된 데이터를 객체로 변환
    1. @Data public static class JoinDTO { private String username; private String password; private String email; public User toEntity(PasswordEncoder passwordEncoder) { // 패스워드 암호화. IoC에 넣어 비밀번호 비교 String encPassword = passwordEncoder.encode(password); User user = new User(null, username, encPassword, email, null); return user; } }
  1. UserRepository save → User 객체를 DB저장
    1. public User save(User user) { em.persist(user); return user; }
  1. UserController join → 회원가입 요청 처리 후, 서비스 반환
    1. @PostMapping("/join") public String join(UserRequest.JoinDTO joinDTO) { userService.회원가입(joinDTO); return "redirect:/login-form"; }
 

4. Spring Security Filter Chain 적용

  • SecurityConfig
  1. 사용자가 로그인 폼(/login-form)에서 로그인 정보를 제출하면, loginProcessingUrl("/login")을 통해 Spring Security가 인증을 처리
  1. 인증 성공 시, successHandler가 호출되어 로그인한 사용자 정보를 세션에 저장하고, 홈 페이지(/)로 리다이렉트
  1. /s/** 경로는 인증된 사용자만 접근할 수 있으며, 나머지 경로는 모두 인증 없이 접근 가능
@Configuration public class SecurityConfig { // user가 입력한 비밀번호와 DB비밀번호와 맞는지 확인 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SecurityFilterChain configure(HttpSecurity http) throws Exception { http.csrf(c->c.disable()); // successHandler 로그인 성공하면 지정한 행위 http.authorizeHttpRequests(r-> r.requestMatchers("/s/**").authenticated().anyRequest().permitAll()) .formLogin(f->f.loginPage("/login-form") .loginProcessingUrl("/login") .successHandler((request, response, authentication) -> { User user = (User) authentication.getPrincipal(); HttpSession session = request.getSession(); session.setAttribute("sessionUser", user); response.sendRedirect("/"); })); return http.build(); } }
  • BoardController 어노테이션 추가
    • AuthenticationPrincipal : Spring Security에서 사용자 정보 담음
@GetMapping("/s/board/save-form") public String saveForm(@AuthenticationPrincipal User user) { System.out.println("로그인 : " + user.getUsername()); return "board/save-form"; }
 
Share article

goho