반응형
이 포스팅은 아래의 강의를 참고하였으니 여기에서 공부하시는 것을 추천드립니다.
1. JWT(JSON Web Token)
- 정보를 JSON 객체로 안전하게 전송하기 위한 개방형 표준(RFC 7519)
- 디지털 서명이 되어 있으므로 신뢰 가능
- RSA or ECDSA 알고리즘을 이용
- 구조
- Header: 토큰 유형과 서명 알고리즘 정보가 담김
- Payload: 엔터티(사용자) 및 추가데이터에 대한 설명. 즉, 통신하고자하는 정보가 담김
- Signature: 서명관련된 정보가 담김
- Signature: ((Header + Payload)를 HS256으로 암호화)를 BASE64로 암호화
- JWT: BASE64(Header).BASE64(Payload).BASE64(HS256(Header+Payload))
2. JWT 사용하기 위한 Spring 설정
1) pom.xml에 아래의 의존성 추가
<!-- jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.19.2</version>
</dependency>
2) CorsConfig 자바 파일 추가
package com.cos.security1.config;
import org.springframework.web.filter.CorsFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter(){
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 내 서버가 응답할 때 JSON을 js에서 처리할 수 있게 할 지 설정
config.addAllowedOrigin("*"); // 모든 ip의 응답을 허용
config.addAllowedHeader("*"); // 모든 geader에 응답을 허용
config.addAllowedMethod("*"); // 모든 Method(post, get, put, delete, patch) 요청 허용
source.registerCorsConfiguration("/api/**", config);
return new CorsFilter(source);
}
}
3) filter 패키지 생성 후 filterConfig 파일 추가
package com.cos.security1.config.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter1> filter1(){
FilterRegistrationBean<MyFilter1> bean = new FilterRegistrationBean<>(new MyFilter1());
bean.addUrlPatterns("/*"); // 모든 요청에 대해서 적용
bean.setOrder(1); // 가장 먼저 실행되도록(낮은 번호가 필터중에서 가장 먼저 실행됨)
return bean;
}
@Bean
public FilterRegistrationBean<MyFilter2> filter2(){
FilterRegistrationBean<MyFilter2> bean = new FilterRegistrationBean<>(new MyFilter2());
bean.addUrlPatterns("/*");
bean.setOrder(0);
return bean;
}
}
4) filter 패키지에 커스텀 필터 파일 추가(테스트용)
필터별로 우선순위가 언제 적용되는 지 확인하기 위하여 아래의 필터들을 만든다.
MyFilter1.java
package com.cos.security1.config.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter1 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("filter1");
chain.doFilter(request, response);
}
}
MyFilter2.java
package com.cos.security1.config.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter2 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("filter2");
chain.doFilter(request, response);
}
}
MyFilter3.java
package com.cos.security1.config.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter3 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("filter3");
chain.doFilter(request, response);
}
}
5) SecurityConfig 파일에서 아래와 같이 수정
Spring Security 기본 로그인 및 Oauth2 설정 부분 주석처리 필요(강의에서 JWT와 설정이 다르다고함)
package com.cos.security1.config;
import com.cos.security1.config.filter.MyFilter1;
import com.cos.security1.config.filter.MyFilter3;
import com.cos.security1.config.oauth2.PrincipalOauth2UserSerivce;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.web.filter.CorsFilter;
// 구글 로그인 과정
// 1. 코드받기(인증) 2. 액세스토큰(권한) 3. 사용자 프로필정보 가져오기 4. 그 정보를 토대로 회원가입 진행
@Configuration
@EnableWebSecurity // spring security filter가 Spring filter chain 에 등록
// securedEnabled: @Secured 어노테이션 활성화. @Secured? 특정 URL에 대해서만 간단하게 권한 처리를 할 수 있는 어노테이션
// prePostEnabled: @PreAuthorize, @PostAuthorize 어노테이션 활성화.
// @PreAuthorize: 해당 메소드 진입 전 처리. @PostAuthorize: 해당 메소드 진입 후 처리
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private PrincipalOauth2UserSerivce principalOauth2UserSerivce;
@Autowired
private final CorsFilter corsFilter;
/**
* password 암호화
* @return
*/
@Bean
public BCryptPasswordEncoder encodePw(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception{ // Spring Security 설정
http.csrf().disable(); // csrf 비활성화
/********* JWT 관련 설정 부분(시작) ******/
// Spring Security 기본 로그인 및 OAuth2를 사용하기 위해서는 아래의 설정 주석 처리 필요
///*
http.addFilterBefore(new MyFilter3(), BasicAuthenticationFilter.class); // BasicAuthenticationFilter 이전에 MyFilter3을 추가하겠다.
// 시큐리티 필터가 커스텀 필터보다 먼저 실행됨
// 커스텀 필터를 시큐리티 필터보다 먼저 실행시키는 방법
// 시큐리티 필터 중, 가장 먼저 실행되는 필터는 SecurityContextPersistenceFilter 이므로 이것보다 앞에 위치하면 됨.0
//http.addFilterBefore(new MyFilter1(), SecurityContextPersistenceFilter.class);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 세션을 사용하지 않겠다라는 의미
.and()
.addFilter(corsFilter) // 인증이 있어야할 때 시큐리티 필터에 등록. (인증이 필요없을 때 해당 컨트롤러에 @CrossOrigin 어노테이션을 사용하면 됨)
.formLogin().disable() // Spring Security 로그인 사용 X
.httpBasic().disable() // http를 제외한 다른 방식(js로 요청 등)을 허용하겠다.
.authorizeRequests()
.antMatchers("/api/v1/user/**")
.access("hasRole('ROLE_USER') or hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
.antMatchers("/api/v1/manager/**")
.access("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
.antMatchers("/api/v1/admin/**")
.access("hasRole('ROLE_ADMIN')")
.anyRequest().permitAll();
//*/
/********* JWT 관련 설정 부분(끝) ******/
/********* Spring Security 기본 로그인 및 Oauth2 설정 부분(시작) ******/
// JWT를 사용하기 위해서는 아래의 설정 주석 처리 필요
/*
// URL에 따른 접근 제한 처리
http.authorizeRequests()
.antMatchers("/user/**").authenticated() // URL user : 인증이 되어야 함
.antMatchers("/manager/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')") // URL manager : 권한 'ROLE_ADMIN', 'ROLE_MANAGER'가 있어야함
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')") // URL admin : 권한 'ROLE_ADMIN'이 있어야함
.anyRequest().permitAll() // 위에 명시되지 않은 URL 은 로그인 및 권한 검사 X
.and()
.formLogin()
.loginPage("/loginForm") // formLogin이 필요한 경우, /loginForm 으로 보낸다.
.loginProcessingUrl("/login") // login 주소가 호출이 되면 시큐리티가 낚이채서 대신 로그인을 진행
.defaultSuccessUrl("/") // login 성공 시, 보내줄 기본 url
// OAuth2 로그인 설정(시작)
.and()
.oauth2Login()
.loginPage("/loginForm") // OAuth2의 로그인 페이지 URL.
.userInfoEndpoint()
.userService(principalOauth2UserSerivce)// 구글 로그인이 완료된 이후에 후 처리가 필요. (코드가 아닌 액세스토큰+사용자프로필의정보)를 가져옴
// OAuth2 로그인 설정(끝)
;
*/
/********* Spring Security 기본 로그인 및 Oauth2 설정 부분(끝) ******/
}
}
3. 필터 우선순위 확인
Controller에 만들어둔 매핑된 아무 주소로 접속 시 아래처럼 나타난다.
이유:
filter3: SecurityConfig 에서 BasicAuthenticationFilter 이전에 MyFilter3을 추가했기 때문에 커스텀 필터 중 가장 먼저 나왔다.
filter1 & filter2: 스프링시큐리티 기본 필터가 끝난 이후 나오며, FilterConfig에서 order에 맞게 우선순위가 나온다.
(우선순위는 숫자가 낮을수록 먼저 높은 우선순위를 가짐)
필터이름 | 우선순위 |
filter1 | 1 |
filter2 | 0 |
반응형
'BE > Spring' 카테고리의 다른 글
[Spring Security] JWT - 4. JWT 로그인 및 권한 처리 (0) | 2022.06.19 |
---|---|
[Spring Security] JWT - 3. JWT 임시 토큰 테스트 및 로그인 시 토큰 생성 (0) | 2022.06.18 |
[Spring Security] JWT - 1. JWT를 공부하기 전에 (0) | 2022.06.09 |
[Spring Security] 네이버 로그인하기 (0) | 2022.06.06 |
[Spring Security] 페이스북 로그인하기 (0) | 2022.06.03 |