Spring Boot JWT Tutorial (3) – JWT 코드, Security 설정 추가

튜토리얼 코드

https://github.com/SilverNine/spring-boot-jwt-tutorial

바로가기

Spring Boot JWT Tutorial (1) – JWT 소개, 프로젝트 생성

Spring Boot JWT Tutorial (2) – Security 기본 설정, Data 설정

Spring Boot JWT Tutorial (3) – JWT 코드, Security 설정 추가

Spring Boot JWT Tutorial (4) – Repository, 로그인

Spring Boot JWT Tutorial (5) – 회원가입, 권한검증

JWT 설정 추가

application.yml

application.yml에 jwt 관련 설정을 추가합니다.

HS512 알고리즘을 사용할 것이기 때문에 secret key는 512bit, 즉 64byte 이상을 사용해야 합니다.

터미널에서 secret key를 base64로 인코딩하여 secret 항목에 채워넣습니다.

$ echo ‘silvernine-tech-spring-boot-jwt-tutorial-secret-silvernine-tech-spring-boot-jwt-tutorial-secret’|base64

build.gradle

build.gradle에 jwt 라이브러리 3개를 추가합니다.

compile group: ‘io.jsonwebtoken’, name: ‘jjwt-api’, version: ‘0.11.2’

runtime group: ‘io.jsonwebtoken’, name: ‘jjwt-impl’, version: ‘0.11.2’

runtime group: ‘io.jsonwebtoken’, name: ‘jjwt-jackson’, version: ‘0.11.2’

JWT 관련 코드 추가

TokenProvider.java

jwt 패키지를 생성한 후 TokenProvider.java 파일을 생성합니다.

TokenProvider 빈은 application.yml에서 정의한 jwt.secret, jwt.token-validity-in-seconds 값을 주입받도록 합니다.

InitializingBean을 구현하고 afterPropertiesSet()을 오버라이드한 이유는 빈이 생성되고 의존성 주입까지 끝낸 이후에 주입받은 secret 값을 base64 decode하여 key 변수에 할당하기 위함입니다.

createToken 메소드는 Authentication 객체에 포함되어 있는 권한 정보들을 담은 토큰을 생성하고

jwt.token-validity-in-seconds 값을 이용해 토큰의 만료 시간을 지정합니다.

getAuthentication 메소드는 토큰에 담겨있는 권한 정보들을 이용해 Authentication 객체를 리턴합니다.

validateToken 메소드는 토큰을 검증하는 역할을 수행합니다.

JwtFilter.java

JWT를 위한 Custom Filter를 만들기 위해 GenericFilterBean을 extends한 JwtFilter.java를 생성합니다.

JwtFilter빈은 TokenProvider를 주입받습니다.

실제 필터링 로직은 doFilter 메소드를 오버라이드하여 작성합니다.

resolveToken 메소드는 HttpServletRequest 객체의 Header에서 token을 꺼내는 역할을 수행합니다.

doFilter 메소드는 jwt 토큰의 인증 정보를 현재 실행중인 스레드 ( Security Context ) 에 저장합니다.

JwtSecurityConfig.java

JwtSecurityConfig.java 는 SecurityConfigurerAdapter를 extends하며 configure메소드를 오버라이드하여 위에서 만든 JwtFilter를 Security 로직에 적용하는 역할을 수행합니다.

JwtAuthenticationEntryPoint.java

유효한 자격증명을 제공하지 않고 접근하려 할때 401 UNAUTHORIZED 에러를 리턴하기 위해 AuthenticationEntryPoint를 구현한 JwtAuthenticationEntryPoint 클래스를 작성합니다.

JwtAccessDeniedHandler.java

필요한 권한이 존재하지 않은 경우 403 FORBIDDEN 에러를 리턴하기 위해 AccessDeniedHandler를 구현한 JwtAccessDeniedHandler 클래스를 작성합니다.

Security 설정 추가

SecurityConfig.java

@EnableGlobalMethodSecurity(prePostEnabled = true) 어노테이션은 메소드 단위로 @PreAuthorize 검증 어노테이션을 사용하기 위해 추가합니다. 

위에서 만들었던 TokenProvider, JwtAuthenticationEntryPoint, JwtAccessDeniedHandler를 주입받는 코드를 추가합니다.

Password Encode는 BCryptPasswordEncoder()를 사용하겠습니다.

우리는 Token 방식을 사용하므로 csrf 설정을 disable 합니다.

예외처리를 위해 만들었던 코드를 지정해줍니다.

데이터 확인을 위해 사용하고 있는 h2-console을 위한 설정을 추가해줍니다.

우리는 세션을 사용하지 않기 때문에 세션 설정을 STATELESS로 지정해줍니다.

/api/hello, /api/authenticate, /api/signup 3가지 API는 Token이 없어도 호출할 수 있도록 허용합니다.

/api/authenticate는 로그인을 위한 API이고 /api/signup 회원가입에 대한 API입니다. 관련 코드는 다음편에서 다루겠습니다.

위에서 만들었던 JwtFilter를 addFilterBefore 메소드로 등록했던 JwtSecurityConfig 클래스도 적용해줍니다.

자 이제 기본적인 JWT, Security 설정이 끝났습니다.

다음편에서는 Database와 연결하는 Repository를 만들고 회원가입, 로그인을 구현하겠습니다.