스프링 시큐리티 처리 과정
스프링 시큐리티 인증 과정
1. 로그인을 하게 되면 AuthenticationFilter에 들어옵니다.
2. UsernamePasswordAuthenticationToken을 통해 유저의 로그인 정보를 만듭니다.
3. AuthenticationManager의 구현체인 ProviderManager가 AuthenticationProvider를 호출합니다.
4. UserDetailsServicesms UserDetails를 구현한 User 클래스를 받아 필터에 필터에 값을 전달합니다.
5. 필터는 받은 값을 SecurityContextHolder의 SecurityContext의 Authentication에 넣습니다.
6. 들어간 로그인 정보는 세션 기반 방식에서 로그인 인증을 수행할 때 필수적으로 체크해야 하는 정보가 됩니다.
SecurityConfig
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
private final DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/", "/login", "/sign-up", "/check-email-token",
"/email-login", "/login-by-email", "/search/study").permitAll()
.mvcMatchers(HttpMethod.GET, "/profile/*").permitAll()
.anyRequest().authenticated();
http.formLogin()
.loginPage("/login").permitAll();
http.logout()
.logoutSuccessUrl("/");
http.rememberMe()
.userDetailsService(userDetailsService)
.tokenRepository(tokenRepository());
}
@Bean
public PersistentTokenRepository tokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
return jdbcTokenRepository;
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.mvcMatchers("/node_modules/**")
.requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}
}
UsernamePasswordAuthenticationFilter
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final StringSPRING_SECURITY_FORM_USERNAME_KEY= "username";
public static final StringSPRING_SECURITY_FORM_PASSWORD_KEY= "password";
private String usernameParameter = "username";
private String passwordParameter = "password";
private boolean postOnly = true;
public UsernamePasswordAuthenticationFilter() {
super(new AntPathRequestMatcher("/login", "POST"));
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} else {
String username = this.obtainUsername(request);
String password = this.obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
@Nullable
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(this.passwordParameter);
}
@Nullable
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(this.usernameParameter);
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
}
public void setUsernameParameter(String usernameParameter) {
Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
this.usernameParameter = usernameParameter;
}
public void setPasswordParameter(String passwordParameter) {
Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
this.passwordParameter = passwordParameter;
}
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public final String getUsernameParameter() {
return this.usernameParameter;
}
public final String getPasswordParameter() {
return this.passwordParameter;
}
}
AccountService
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class AccountService implements UserDetailsService {
@Transactional(readOnly = true)
@Override
public UserDetails loadUserByUsername(String emailOrNickname) throws UsernameNotFoundException {
Account account = accountRepository.findByEmail(emailOrNickname);
if (account == null) {
account = accountRepository.findByNickname(emailOrNickname);
}
if (account == null) {
throw new UsernameNotFoundException(emailOrNickname);
}
return new UserAccount(account);
}
}
'스프링 부트' 카테고리의 다른 글
DTO vs VO vs Entity 비교 (0) | 2022.04.04 |
---|---|
[스프링부트] MongoDB로 CRUD 실습해보기 (0) | 2022.03.02 |
[스프링부트] javax.persistence와 org.springframework.data.annotation의 차이 (0) | 2022.03.02 |
스프링부트 Application.properties에서 H2 설정 하는법 (0) | 2022.01.19 |
김영한 스프링의 핵심 원리 정리 (0) | 2022.01.19 |
댓글