Spring Security 필터 체인(Filter Chain) 적용 -기존 필터 삭제
Spring Security에서 HTTP 요청을 처리할 때 적용되는 여러 개의 보안 필터들의 순차적 집합.보안 필터들이 요청을 처리하는 순서를 정의, 이를 통해 보안 관련 작업을 효율적 처리 가능
0. Filter와 Security 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. 회원가입 기능 구현
UserSevice
회원가입 메서드
@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에 반환값 받기
}
}
UserRequest
JoinDTO → 회원가입시 입력된 데이터를 객체로 변환
@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;
}
}
UserRepository
save → User 객체를 DB저장
public User save(User user) {
em.persist(user);
return user;
}
UserController
join → 회원가입 요청 처리 후, 서비스 반환
@PostMapping("/join")
public String join(UserRequest.JoinDTO joinDTO) {
userService.회원가입(joinDTO);
return "redirect:/login-form";
}
4. Spring Security Filter Chain 적용
SecurityConfig
- 사용자가 로그인 폼(
/login-form
)에서 로그인 정보를 제출하면,loginProcessingUrl("/login")
을 통해 Spring Security가 인증을 처리
- 인증 성공 시,
successHandler
가 호출되어 로그인한 사용자 정보를 세션에 저장하고, 홈 페이지(/
)로 리다이렉트
/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