security config에서 SecurityFilterChain을 작성한다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.headers()
.frameOptions()
.disable()
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/resume").permitAll()
.antMatchers("/items/**").hasRole(Role.USER.name())
.anyRequest().authenticated()
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error=true")
.usernameParameter("email")
.passwordParameter("pwd")
.loginProcessingUrl("/login")
.successHandler(loginSuccesHandler)
.failureHandler(loginFailureHandler)
.and()
.oauth2Login()
.loginPage("/login")
.successHandler(loginSuccesHandler)
.failureHandler(loginFailureHandler)
.userInfoEndpoint()
.userService(customOauth2UserService);
return http.build();
}
로그인 성공 핸들러 작성한다.
@Component
public class LoginSuccesHandler implements AuthenticationSuccessHandler {
private RedirectStrategy redirectStratgy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
String email = authentication.getName();
boolean isUser = authorities.contains(new SimpleGrantedAuthority(Role.USER.getKey()));
if (isUser) {
inputUser(request, email);
redirectStratgy.sendRedirect(request, response, "/items/list");
} else {
inputGuest(request,email);
redirectStratgy.sendRedirect(request, response, "/");
}
}
private void inputUser(HttpServletRequest request, String email){
if(request.getSession().getAttribute("user") == null ){
request.getSession().setAttribute("user", SessionUser.builder().name(email).role(Role.USER).build());
}
}
private void inputGuest(HttpServletRequest request, String email){
if(request.getSession().getAttribute("user") == null ){
request.getSession().setAttribute("user", SessionUser.builder().name(email).role(Role.GUEST).build());
}
}
}
로그인 실패 핸들러 작성한다.
@Slf4j
@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
log.error("로그인 실패 = {}",exception.getMessage());
response.sendRedirect("/login?error=true");
}
}
userService를 작성한다.
@Slf4j
@RequiredArgsConstructor
@Service
public class UserService implements UserDetailsService {
@Autowired
UserRepository userRepository;
@Transactional
public Long joinUser(UserDto userDto) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
userDto.setPwd(passwordEncoder.encode(userDto.getPwd()));
return userRepository.save(userDto.toEntity()).getId();
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = findByEmail(username);
if (user != null) {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(Role.USER.getKey()));
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPwd(), authorities);
} else {
throw new UsernameNotFoundException(username);
}
}
public User findByEmail(String username) {
return userRepository.findByEmail(username).orElse(null);
}
}