시큐리티 설정 파일
SecurityConfig
@RequiredArgsConstructor
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() { // 패스워드 암호화 방식 지정
return new BCryptPasswordEncoder();
}
private final LoginLogService loginLogService;
@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
http.headers(httpSecurityHeadersConfigurer ->
httpSecurityHeadersConfigurer.frameOptions(frameOptionsConfig ->
frameOptionsConfig.sameOrigin()))
// CSRF 보호를 비활성화합니다.
.csrf(c -> c.disable())
// 요청 인증 설정
.authorizeHttpRequests(r ->
r.requestMatchers("/s/**") // s로 시작하는 모든 요청은 인증 필요
.authenticated()
.anyRequest()
.permitAll())
// 로그인 설정
.formLogin(f ->
f.loginPage("/login-form")
.loginProcessingUrl("/login")
.successHandler((request, response, authentication) -> {
User user = (User) authentication.getPrincipal();
HttpSession session = request.getSession();
session.setAttribute("sessionUser", user);
String userAgent = request.getHeader("User-Agent");
loginLogService.save(user, userAgent);
response.sendRedirect("/main");
}))
// 로그아웃 설정
.logout(l ->
l.logoutUrl("/logout")
.logoutSuccessUrl("/main")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
);
return http.build();
}
}
로그인 설정
.formLogin(f ->
f.loginPage("/login-form")
.loginProcessingUrl("/login")
.successHandler((request, response, authentication) -> {
User user = (User) authentication.getPrincipal();
HttpSession session = request.getSession();
session.setAttribute("sessionUser", user);
String userAgent = request.getHeader("User-Agent");
loginLogService.save(user, userAgent);
response.sendRedirect("/main");
위 설정이 자동으로 구현해주는 로그인 메서드
@PostMapping("/login")
public String login(User user) {
session.setAttribute("sessionUser", user);
return "redirect:/main";
}
- session 에 저장된 sessionUser 정보는 Controller에서 @AuthenticationPrincipal 어노테이션으로 가져올 수 있습니다.
@Controller
public class UserController {
@GetMapping("/profile")
public String getUserProfile(@AuthenticationPrincipal User user, Model model) {
model.addAttribute("user", user);
return "profile";
}
}
로그아웃 설정
.logout(l ->
l.logoutUrl("/logout")
.logoutSuccessUrl("/main")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID"));
위 설정이 자동으로 구현해주는 로그아웃 메서드
@PostMapping("/logout")
public String logout(HttpServletRequest request) {
HttpSession session = request.getSession();
if (session != null) {
session.invalidate(); // 세션 무효화
}
// 쿠키 삭제
javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie("JSESSIONID", null);
cookie.setPath("/");
cookie.setMaxAge(0);
response.addCookie(cookie);
return "redirect:/main";
}
User (회원) 엔티티
@NoArgsConstructor
@Getter
@Table(name = "user_tb")
@Entity
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// email을 username으로 사용
@Column(unique = true, nullable = false)
private String email;
@Column(nullable = false)
private String password;
// username 대신 email을 반환
@Override
public String getUsername() {
return email;
}
@Override
public String getPassword() {
return password;
}
// 권한 확인(role -> admin, manager, guest 같은)
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of();
}
// 계정이 만료되지 않았는지 확인합니다.
@Override
public boolean isAccountNonExpired() {
return true;
}
// ID 잠금 여부를 확인합니다.
@Override
public boolean isAccountNonLocked() {
return true;
}
// 비밀번호가 만료되지 않았는지 확인합니다.
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// 계정 비활성화 여부를 확인합니다.
@Override
public boolean isEnabled() {
return true;
}
}
- 스프링이 검증할 회원 엔티티는 implements UserDetails 이 필요합니다.
- Spring Security는 기본적으로 username과 password를 체크할 수 있도록 설정됩니다.
- 비밀번호 비교가 제대로 작동하려면 비밀번호를 해시화해서 저장해야 합니다.
// username 대신 email을 반환
@Override
public String getUsername() {
return email;
}
- username 대신 email 비교를 하고 싶다면 getter을 Override합니다.
Share article