Spring Security
개요
springboot 모듈중 하나로 spring-security을 통해서 접근 권한을 확인하여 사용자의 접근권한을 확인한다. 해당 방식은 spring Security 3.x 기준이다. 2버전에서는 람다식으로 받는 파라미터가 없어서 람다식으로 구현안되어 있다.
동작원리
- 사용자 요청
- UsernamePasswordAuthenticationFilter가 로그인 처리
- AuthenticationManager가 인증을 시도
- UserDetailsService에서 사용자 정보 조회
- 비밀번호 검증
- 인증 성공시
application에 요청을 보내면 Container 안에 있는 Filter를 거쳐서 인증작업을 진행함 그런데 이런 인증작업을 하는 filter를 Spring Security Config를 통해서 만드는 것을 자동으로 해주는 library
요청 -> (filter -> controller) : ()는 spring Container
단방향 해시 암호화
- BCrypt Password Encoder 사용할 예정
- 암호화만 가능하고 복호화는 못하는 암호화
// CORS 설정
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Arrays.asList("http://spring.koosang-project.com"));
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","PATCH"));
config.setAllowCredentials(true);
config.setExposedHeaders(Arrays.asList("Authorization", "Authorization-refresh"));
config.setAllowedHeaders(Arrays.asList("Authorization", "Authorization-refresh", "Cache-Control", "Content-Type"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
//CORS 설정변경
http.cors(corsConfigurer ->
corsConfigurer.configurationSource(corsConfigurationSource())
);
//CSRF 토큰을 비활성화 한다
http.csrf(csrfConfigurer -> csrfConfigurer.disable()); // scrf 토큰을 받지 않겠다.
// 인증/인가 설정
http.authorizeHttpRequests(authorize ->
authorize
// URL 경로 member 에는 인증 성공필요
.requestMatchers("/api/d1/member/**").authenticated()
// // URL 경로 manager 에는 인증 성공 + MANAGER 권한
.requestMatchers(new AntPathRequestMatcher("/api/d1/manager/**"))
.hasAnyRole("MANAGER", "ADMIN")
// .requestMatchers(new AntPathRequestMatcher("/api/d1/admin/**"))
// .hasRole("ADMIN")
// 나머지 모든 권한에 한해 모두 접근 허용
.anyRequest().permitAll()
);
// 로그인 설정
http.formLogin(auth ->
auth
.successHandler(new MyAuthenticationSuccessHandler())
.failureHandler((request, response, authentication) -> {
System.out.println("인증실패");
response.setStatus(401);
})
.loginProcessingUrl("/api/d1/login")
);
// 권한 없음 페이지
http.exceptionHandling(exception ->
exception.authenticationEntryPoint(
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)
)
);
// 로그아웃 설정
http.logout(auth ->
auth
.logoutSuccessHandler((request, response, authentication) -> {
System.out.println("logout성공");
response.setStatus(200);
})
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.logoutUrl("/api/d1/logout")
.permitAll()
);
// 사용자 정의 UserDetailsService 적용
http.userDetailsService(detailsService);
// 다중로그인 허용여부 설정
http.sessionManagement(auth ->
auth.maximumSessions(1).maxSessionsPreventsLogin(true)
);
http.sessionManagement(auth -> auth.sessionFixation().changeSessionId());
return http.build();
}