구동원리
- 클라이언트에서 HTTP request
- sequrityFilterChain에서 HTTP 요청 가로챔
- (FilterChain 중 UsernamePasswordAuthenticationFilter에서)
클라이언트 폼으로 받은 아이디/비밀번호를 sequrity 토큰에 맞추고
UserNamePasswordAuthenticationToken객체를 생성한다. - (FilterChain이 감지한 인증 요청의) 인증수행을 『ProviderManager(interface)』 에게 위임하며,
여러 구현체(Provider)을 통해 인증을 수행AuthenticationManager는 실질적인 인증을 수행하기 위하여 List 형태로 Provide들을 가지고 있다. - ProviderManager 중 『DaoAuthenticationProvider』 내부적으로 "UserDetailsService"를 호출
- UserDetailsService를 구현한 로직이 UserDetails를 구현한 객체를 반환
- 인증수행을 마치고 UserDetails로 반환된 객체가 SecutiryContextHolder에 저장
□ SecurityContextHolder
- 인가받은 유저 Detail 정보를 저장하는 컨텍스트, 세션으로 이해하면 된다.
- 『 authentication관련 정보를 포함한 유저 정보 』가 있는 SecurityContext를 포함한다.
구조
구현
※ mapper와 controller, view 부분은 생략
SecurityConfig : SequrityFilterChain 설정
@Configuration
@EnableWebSecurity
@Slf4j
public class SecurityConfig {
// sequrityChain에서 매개값으로 들어온 클라이언트 http request를 가로챔
// sequrity http request 설정으로 변환하여 빌드, SecurityFilterChain 객체로 반환한다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// csrf 설정 : 패스워드 암호화시 사용하는 메서드
http.csrf(AbstractHttpConfigurer::disable); // 메서드 참조 이용
// URL 접근 권한 설정
http.formLogin(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((authorize) -> authorize.requestMatchers("/").permitAll()
.requestMatchers("/loginForm").permitAll()
.requestMatchers("/WEB-INF/view/**").permitAll()
.anyRequest().authenticated());
// 로그인 요청 설정
// AuthenticationFilter에서 허가, 인증하지 않은 요청은 /loginForm 요청(Controller)
http.formLogin(formLogin -> formLogin.loginPage("/loginForm") // 로그인 페이지 URL 설정
.usernameParameter("id") // UserNamePasswordAuthenticationToken - Sequrity 토큰 중 UserName를 "id"와 매칭
.passwordParameter("pw") // UserNamePasswordAuthenticationToken - Sequrity 토큰 중 Password를 "pw"와 매칭
.loginProcessingUrl("/loginAction") // 클라이언트에서 /loginAction 액션 시, UserDetailsService를 호출 <- 해당 폼을 바탕으로 UserDetails 객체 생성
.successHandler(loginSuccessHandler())
.failureHandler(loginFailureHandler()));
// 로그아웃
http.logout((logout) -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/loginForm")
.invalidateHttpSession(true));
return http.build();
}
}
UserDetail 구현
@Data
// DAO인 Member를 UserDetails와 호환이 되는 타입(MemberUserDetails)으로 커스터마이징
public class MemberUserDetails implements UserDetails {
Member member;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// 롤을 구현하는 부분
return null;
}
@Override
public String getPassword() { // DAO 중에 무엇을 sequrity의 password로 쓸건지 설정
return member.getPw();
}
@Override
public String getUsername() { // DAO 중에 무엇을 sequrity의 userName으로 쓸건지 설정
return member.getId();
}
}
UserDetailsService 구현
@Service
@Slf4j
public class MemberUserDetailsService implements UserDetailsService {
@Autowired
MemberMapper memberMapper;
// Member타입을 UserNamePasswordAuthenticationToken에 맞는 타입으로 변환하여
// DB에서 가져온 아이디를 sequrity 인가를 받도록 한다.
@Override
public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
Member member = memberMapper.selectMemberById(id); // DB에서 ID를 찾는 메서드
MemberUserDetails userDetails = new MemberUserDetails();
userDetails.setMember(member);
return userDetails;
}
}
Architecture :: Spring Security
The Security Filters are inserted into the FilterChainProxy with the SecurityFilterChain API. Those filters can be used for a number of different purposes, like exploit protection,authentication, authorization, and more. The filters are executed in a speci
docs.spring.io
'SPRING' 카테고리의 다른 글
Spring JPA (0) | 2025.02.13 |
---|---|
AOP (작성중) (0) | 2025.01.31 |
Entity·DTO·VO와 사용범위, 변환방법 (0) | 2025.01.11 |
스프링 컨테이너와 싱글톤 컨테이너 (0) | 2024.12.29 |
Spring Bean과 빈 조회하기 (0) | 2024.12.25 |