- SecurityFilterChain : 기존에 2.x버전에서 WebSecurityConfigurerAdapter 상속받아 configure 재정의하던 방식에서 @Bean으로 생성하도록 변경되었다
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf((csrf) -> csrf.disable())
.authorizeHttpRequests(request -> request.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.requestMatchers(staticPath.toArray(new String[0])).permitAll()
.requestMatchers("/", "/inventory/**", "/account/**", "/api/**")
.permitAll()
.requestMatchers("/admin/**", "/report/**").hasAnyRole( AdminRole.MANAGER.name(), AdminRole.ADMIN.name())
.requestMatchers("/manage/**").hasAnyRole(AdminRole.USER.name(), AdminRole.ADMIN.name())
.anyRequest()
.authenticated())
.formLogin(Customizer.withDefaults())
.build();
}
- PasswordEncoder : @Bean으로 생성해줘야 한다. 주로 BCryptPasswordEncoder 를 많이 사용한다.
- BCryptPasswordEncoder 는 해쉬값이 동일한 것을 방지하기 위해, 해쉬처리의 반복과 솔트처리(원문에 임의의 문자열 붙이기)를 이용
- strengh는 반복횟수에 영향을 주어 크게 줄 경우 해쉬작업이 오래걸릴 수 있음. salt처리를 통해
- BCryptPasswordEncoder 는 생성할때 strength(4~31)와 random 값을 줄 수 있는데,
특별히 지정하지 않으면 strength 는 10을 사용하고, random값은 자체적으로 SecureRandom을 주입해준다.
public BCryptPasswordEncoder(BCryptVersion version, int strength, SecureRandom random) {
if (strength != -1 && (strength < BCrypt.MIN_LOG_ROUNDS || strength > BCrypt.MAX_LOG_ROUNDS)) {
throw new IllegalArgumentException("Bad strength");
}
this.version = version;
this.strength = (strength == -1) ? 10 : strength;
this.random = random;
}
private String getSalt() {
if (this.random != null) {
return BCrypt.gensalt(this.version.getVersion(), this.strength, this.random);
}
return BCrypt.gensalt(this.version.getVersion(), this.strength);
}
public static String gensalt(String prefix, int log_rounds) throws IllegalArgumentException {
return gensalt(prefix, log_rounds, new SecureRandom());
}
- UserDetailsService 를 구현한 Bean을 등록해줘야 한다
@RequiredArgsConstructor
@Service
public class AuthorizationService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findById(username).get();
Set<GrantedAuthority> grantedAuthority = new HashSet<>();
grantedAuthority.add(new SimpleGrantedAuthority(user.getRoleKey()));
return new org.springframework.security.core.userdetails.User(user.getUserId(), user.getPassword(), grantedAuthority);
}
}
- 추가로 로그인 성공시 동작을 구현할 수 있다. AuthenticationSuccessHandler
@RequiredArgsConstructor
@Service
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private final HttpSession httpSession;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
httpSession.setAttribute("login_user", userDetails.getUsername());
response.sendRedirect("redirect:/");
}
}
반응형