사용자가 자격 증명 정보를 제출하면, AbstractAuthenticationProcessingFilter가 Authentication 객체를 생성합니다.
Authentication 객체가 AuthenticationManager에게 전달됩니다.
인증에 실패하면, 로그인 된 유저정보가 저장된 SecurityContextHolder의 값이 지워지고 RememberMeService.joinFail()이 실행됩니다. 그리고 AuthenticationFailureHandler가 실행됩니다.
인증에 성공하면, SessionAuthenticationStrategy가 새로운 로그인이 되었음을 알리고, Authentication 이 SecurityContextHolder에 저장됩니다. 이후에 SecurityContextPersistenceFilter가 SecurityContext를 HttpSession에 저장하면서 로그인 세션 정보가 저장됩니다.
그 뒤로 RememberMeServices.loginSuccess()가 실행됩니다. ApplicationEventPublisher가 InteractiveAuthenticationSuccessEvent를 발생시키고 AuthenticationSuccessHandler 가 실행됩니다.
*참조
https://www.elancer.co.kr/blog/view?seq=235
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.2.3</version>
</dependency>
의존성을 추가하면 설정하지 않아도 로그인 창이 뜬다.
@Bean
public InMemoryUserDetailsManager createUserDetailManager() {
//InMemoryUserDetailsManager
//사용자의 인증 및 권한부여 처리.
//개발자가 사용자의 상세 정보를 코드 내에 직접 정의하고 구성
//간단한 애플리케이션 또는 개발 및 테스트 목적으로 사용될 수 있다.
UserDetails userDetails1 = createNewUser("soo", "1234");
UserDetails userDetails2 = createNewUser("loo", "1234");
return new InMemoryUserDetailsManager(userDetails1, userDetails2 );
}
private UserDetails createNewUser(String username, String password) {
Function<String, String> passwordEncoder
= input -> passwordEncoder().encode(input);
//받은 문자열을 passwordEncoder() 메서드로 전달하여 암호화한 후 반환.
//비밀번호를 입력받아 BCryptPasswordEncoder를 사용하여 암호화한 결과를 반환하는 함수
UserDetails userDetails = User.builder().passwordEncoder(passwordEncoder)
.username(username)
.password(password)
.roles("USER", "ADMIN")
.build();
return userDetails;
}
Spring Security는 UserDetails 인터페이스의 구현체를 직접적으로 보안 목적으로 사용하지는 않습니다.
대신에 UserDetails 인터페이스의 구현체는 사용자 정보를 저장하고 나중에 Authentication 객체로 캡슐화됩니다.
이를 통해 보안과 관련이 없는 사용자 정보(예: 이메일 주소, 전화번호 등)를 편리한 위치에 저장할 수 있습니다.
Authentication에서 사용자의 정보값을 불러올 수 있다!
createNewUser: 사용자 이름과 비밀번호를 사용하여 UserDetails 객체를 생성
private String getLoggedInUsername(ModelMap model) {
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication(); //사용자 정보를 Security에서 받아올 것
return authentication.getName();
}
```
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
auth -> auth.anyRequest().authenticated());
http.formLogin(withDefaults());
http.csrf().disable();
http.headers().frameOptions().disable();
return http.build();
//command + shift + t
//command + o
}
authorizeHttpRequests(): HTTP 요청에 대한 보안 규칙을 정의. anyRequest().authenticated()는 모든 요청에 대해 인증이 필요하다는 것을 의미합니다. 다시 말해, 모든 요청은 인증된 사용자에게만 허용됩니다.
formLogin(): 폼 기반 로그인을 활성화합니다. 이는 사용자가 로그인 페이지로 리디렉션되어 자격 증명을 제출할 수 있도록 합니다. -> 로그인 창이 뜬다!
csrf().disable(): CSRF(Cross-Site Request Forgery) 보호를 비활성화합니다. 이렇게 하면 CSRF 공격에 대한 보호가 제거됩니다.CSRF disable -> H2Database에 접근하려면 CSRF를 비활성 해주어야 한다.
headers().frameOptions().disable(): X-Frame-Options 헤더를 비활성화합니다. 이는 웹 애플리케이션의 내부 페이지를 외부 프레임에서 로드할 수 있도록 합니다.
마지막으로 http.build()를 호출하여 설정한 보안 필터 체인을 빌드하고 반환합니다. 이렇게 하면 필터 체인이 구성되고 Spring Security가 이를 적용할 수 있게 됩니다.