- [Spring] 스프링 심화 - Spring Security 1
- 적용하기
- Spring Security의 요소 확인
- [Spring] 스프링 심화 - Spring Security 2
- Default Form Login 방식 사용
- UserDetails, UserDetailsService custom
- 비밀번호 암호화 이해 및 적용
- [Spring] 스프링 심화 - Spring Security 3
- CustomSecurityFilter 적용
- @AuthenticationPrincipal
- @Secured
- ExceptionHandling - 401, 403
# 미리 지정 가능
spring.security.user.name=user
spring.security.user.password=1234
@Override로 사용
HttpSecurity 클래스
1. build.gradle
2. WebSecurityConfig
# build.gradle
// 스프링 시큐리티
implementation 'org.springframework.boot:spring-boot-starter-security'
# WebSecurityConfig
@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable(); // CSRF 설정
http.authorizeRequests().anyRequest().authenticated();
http.formLogin(); // 로그인 사용
return http.build();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/images/**").permitAll() // image 폴더를 login 없이 허용
.antMatchers("/css/**").permitAll()
.anyRequest().authenticated() // 어떤 요청이든 '인증'
.and()
// 로그인 기능 허용
.formLogin()
.loginPage("/user/login")
.defaultSuccessUrl("/")
.failureUrl("/user/login?error")
.permitAll()
.and()
// 로그아웃 기능 허용
.logout()
.permitAll();
}
}
🔥 CSRF란?
- CSRF(사이트 간 요청 위조, Cross-site request forgery)
- 공격자가 인증된 브라우저에 저장된 쿠키의 세션 정보를 활용하여 웹 서버에 사용자가 의도하지 않은 요청을 전달하는 것
- CSRF 설정이 되어있는 경우 html 에서 CSRF 토큰 값을 넘겨주어야 요청을 수신 가능
- 쿠키 기반의 취약점을 이용한 공격 이기 때문에 REST 방식의 API에서는 disable 가능
- POST 요청마다 처리해 주는 대신 CSRF protection 을 disable
- form login 기반은 인증이 필요한 URL 요청이 들어왔을 때 인증이 되지 않았다면 로그인 페이지를 반환하는 형태
# 예시코드
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication auth = new UsernamePasswordAuthenticationToken
(principal, credentials, authorities);
context.setAuthentication(auth);
SecurityContextHolder.setContext(context);
- SecurityContext
- SecurityContextHolder로 접근할 수 있으며 Authentication 객체를 가지고 있음.
SecurityContext
에서 가져올 수 있음principal
: 사용자를 식별credential
: 주로 비밀번호, 대부분 사용자 인증에 사용하고 난 다음 비움authorities
: 사용자에게 부여한 권한을 GrantedAuthority로 추상화하여 사용# UserDetails
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
UserRoldEnum role = user.getRole();
String authority = role.getAuthority(); // {"ROLE_USER"}
SimpleGrantedAuthority sgAuth = new SimpleGrantedAuthority(authority);
Collection<GrantedAuthority> authorities = new ArrayLsit<>();
authorities.add(simpleGrantedAuthority);
return authorities;
}
Authentication auth = new UsernamePasswordAuthenticationToken
(userDetails, null, userDetails.getAuthorities());
-> UsernamePasswordAuthenticaionToken은 Authentication을 implements한
AbstractAuthenticationToken의 하위 클래스로, 인증객체를 만드는데 사용됨.
UserDetails
를 반환UserDetails
는 UsernamePasswordAuthenticationToken 타입의 Authentication
을 만들 때 사용되며 해당 인증객체는 SecurityContextHolder
에 세팅
UserDetailsService
가 DB에 접근하여 user 객체를 가져와서 검증UserDetails
는 가져온 user의 정보를 활용해서 만든 객체
-> 필터를 만들어서 위 두가지 활용하기