728x90
설정
build.gradle
...
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
}
코드
WebSecurityConfig.java
import com.fasterxml.jackson.databind.ObjectMapper;
@RequiredArgsConstructor
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final ObjectMapper mapper;
// 로그인, token 검증하는 provider
private final JwtLoginAuthenticationProvider jwtAuthenticationProvider;
private final JwtHeaderAuthenticationFailureHandler jwtHeaderAuthenticationFailureHandler;
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.ignoring().antMatchers("/static/**");
web.ignoring().antMatchers("/dist/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// cors 전체 열기 - 테스트용
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin(CorsConfiguration.ALL);
configuration.addAllowedMethod(CorsConfiguration.ALL);
configuration.addAllowedHeader(CorsConfiguration.ALL);
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
http.httpBasic().disable()
.csrf().disable()
.cors().configurationSource(source)
.and().headers().frameOptions();//
http.authorizeRequests()
.antMatchers("/api/**").hasAnyRole("USER")
.antMatchers("/auth/login").permitAll();
http.authorizeRequests()
.and()
.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler())
.and()
.addFilterBefore(jwtAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Override
// provider 등록
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(jwtAuthenticationProvider);
}
@Bean
public AccessDeniedHandler customAccessDeniedHandler() {
return new CustomAccessDeniedHandler(mapper);
}
@Bean
protected JwtLoginAuthenticationProcessingFilter jwtAuthenticationProcessingFilter() throws Exception {
AntPathRequestMatcher matcher = new AntPathRequestMatcher("/auth/login", HttpMethod.POST.name());
JwtLoginAuthenticationProcessingFilter filter
= new JwtLoginAuthenticationProcessingFilter(matcher, jwtAuthenticationSuccessHandler, jwtAuthenticationFailureHandler);
filter.setAuthenticationManager(authenticationManagerBean());
return filter;
}
}
JwtLoginAuthenticationProvider.java
import org.springframework.stereotype.Component;
import org.springframework.security.authentication.*;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Component
public class JwtLoginAuthenticationProvider implements AuthenticationProvider {
private final AdminUserRepository adminUserRepository;
private final PasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// authenticate하는 기능 생략
return new UsernamePasswordAuthenticationToken("<토큰>", "<비밀번호>", Collections.singletonList(new SimpleGrantedAuthority("USER"))); // "USER"뿐 아니라 다른 ADMIN 등으로 분화하여 나중에 security에서 관리가능
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
JwtLoginAuthenticationSuccessHandler.java
import org.springframework.stereotype.Component;
import org.springframework.security.authentication.*;
import lombok.RequiredArgsConstructor;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
@RequiredArgsConstructor
@Component
public class JwtLoginAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
// provider에서 아무 exception이 발생하지 않고 정상적으로 진행됐을때 진행되는 곳
}
}
JwtLoginAuthenticationFailureHandler.java
import org.springframework.stereotype.Component;
import org.springframework.security.authentication.*;
import lombok.RequiredArgsConstructor;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
@RequiredArgsConstructor
@Component
public class JwtHeaderAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
// provider에서 exception 발생시에 진행되는 곳
}
}
JwtLoginAuthenticationProcessingFilter
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
public class JwtLoginAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
private final AuthenticationSuccessHandler successHandler;
private final AuthenticationFailureHandler failureHandler;
public JwtLoginAuthenticationProcessingFilter(RequestMatcher defaultUrlMatcher, AuthenticationSuccessHandler successHandler, AuthenticationFailureHandler failureHandler) {
super(defaultUrlMatcher);
this.successHandler = successHandler;
this.failureHandler = failureHandler;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// 이메일, 비밀번호 가져오기 생략
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("<이메일>", "<비밀번호>");
return this.getAuthenticationManager().authenticate(authRequest);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
successHandler.onAuthenticationSuccess(request, response, authResult);
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
failureHandler.onAuthenticationFailure(request, response, failed);
}
}
728x90
'개발 > java,spring,springboot' 카테고리의 다른 글
Spring boot jpa datasource 여러 개 설정(multiple datasource) (2) | 2021.04.07 |
---|---|
Spring scheduling + cron (0) | 2021.04.07 |
jwt 설정하기 (spring boot) (0) | 2021.04.01 |
jpa Converter를 이용한 암복호화 (0) | 2021.03.30 |
spring fox 적용하기(springboot) - 자동문서화 (0) | 2020.12.17 |
댓글