From 3191fa694c2c8b7de4af7d212ef8d05175ab7b43 Mon Sep 17 00:00:00 2001 From: choisungwook Date: Sat, 11 Dec 2021 13:28:29 +0900 Subject: [PATCH] =?UTF-8?q?JKT=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20#1?= =?UTF-8?q?46?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 7 +- .../security/filter/JWTCheckFilter.java | 66 ++++++++++++++----- .../ciat/config/security/jwt/JWTUtils.java | 21 ++---- .../config/security/jwt/JWTVerifyResult.java | 14 +--- 4 files changed, 59 insertions(+), 49 deletions(-) diff --git a/backend/build.gradle b/backend/build.gradle index 2a74cf8..953f083 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -20,8 +20,9 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-security' // 필요할 때 주석 해제하고 사용 + implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6' implementation group: 'com.github.ulisesbocchio', name: 'jasypt-spring-boot-starter', version: '3.0.3' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' @@ -34,13 +35,9 @@ dependencies { implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2' implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-aws', version: '2.2.6.RELEASE' - -// implementation 'org.springframework.session:spring-session-jdbc' - runtimeOnly 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' - implementation 'com.sun.xml.bind:jaxb1-impl:2.2.5.1' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" } diff --git a/backend/src/main/java/com/infp/ciat/config/security/filter/JWTCheckFilter.java b/backend/src/main/java/com/infp/ciat/config/security/filter/JWTCheckFilter.java index 1deb47e..7ef1993 100644 --- a/backend/src/main/java/com/infp/ciat/config/security/filter/JWTCheckFilter.java +++ b/backend/src/main/java/com/infp/ciat/config/security/filter/JWTCheckFilter.java @@ -1,5 +1,8 @@ package com.infp.ciat.config.security.filter; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.google.gson.JsonObject; import com.infp.ciat.config.auth.PrincipalDetails; import com.infp.ciat.config.security.jwt.JWTUtils; import com.infp.ciat.config.security.jwt.JWTVerifyResult; @@ -17,6 +20,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.PrintWriter; import java.util.Optional; /*** @@ -50,25 +54,51 @@ protected void doFilterInternal( return; } - JWTVerifyResult verify_result = this.jwtUtils.verify(authorization.substring("Bearer ".length())); - if(verify_result.isStatus()){ - Optional user = accountService.findUserByEmailOrNull(verify_result.getUser()); - if(!user.isPresent()){ - log.error("JWT토큰 검사는 성공했지만 계정이 존재하지 않음(계정이 삭제된 경우)"); - throw new UsernameNotFoundException("사용자가 존재하지 않습니다."); - } + JWTVerifyResult verify_result = null; + try{ + verify_result = this.jwtUtils.verify(authorization.substring("Bearer ".length())); + }catch(TokenExpiredException ex){ + log.error("[Auth]JWTtoken is expired"); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.setStatus(HttpStatus.UNAUTHORIZED.value()); - // 스프링시큐리티 인증정보 초기화(인가설정 적용을 위해) - PrincipalDetails principalDetails = new PrincipalDetails(user.get()); - UsernamePasswordAuthenticationToken auth_token = new UsernamePasswordAuthenticationToken( - principalDetails, - null, - principalDetails.getAuthorities() - ); - SecurityContextHolder.getContext().setAuthentication(auth_token); - filterChain.doFilter(request, response); - }else { - response.setStatus(HttpStatus.FORBIDDEN.value()); + PrintWriter out = response.getWriter(); + JsonObject json = new JsonObject(); + json.addProperty("error", "JWT error"); + json.addProperty("error_deatils", "JWT token is expired"); + out.print(json); + out.flush(); + return; + }catch(JWTVerificationException ex){ + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.setStatus(HttpStatus.BAD_REQUEST.value()); + + PrintWriter out = response.getWriter(); + JsonObject json = new JsonObject(); + json.addProperty("error", "JWT error"); + json.addProperty("error_deatils", "JWT Format is not unvalid"); + out.print(json); + out.flush(); + return; } + + Optional user = accountService.findUserByEmailOrNull(verify_result.getUser()); + if(!user.isPresent()){ + log.error(String.format("[Auth]JWT Token is passed. but %s is not exist", verify_result.getUser())); + throw new UsernameNotFoundException(String.format("%s is not exist. but try login", verify_result.getUser())); + } + + // 스프링시큐리티 인증정보 초기화(인가설정 적용을 위해) + PrincipalDetails principalDetails = new PrincipalDetails(user.get()); + UsernamePasswordAuthenticationToken auth_token = new UsernamePasswordAuthenticationToken( + principalDetails, + null, + principalDetails.getAuthorities() + ); + SecurityContextHolder.getContext().setAuthentication(auth_token); + + filterChain.doFilter(request, response); } } diff --git a/backend/src/main/java/com/infp/ciat/config/security/jwt/JWTUtils.java b/backend/src/main/java/com/infp/ciat/config/security/jwt/JWTUtils.java index 835a0f7..1889013 100644 --- a/backend/src/main/java/com/infp/ciat/config/security/jwt/JWTUtils.java +++ b/backend/src/main/java/com/infp/ciat/config/security/jwt/JWTUtils.java @@ -2,7 +2,6 @@ import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; -import com.auth0.jwt.exceptions.JWTVerificationException; import com.auth0.jwt.interfaces.DecodedJWT; import org.springframework.security.core.GrantedAuthority; import java.time.Instant; @@ -12,7 +11,8 @@ public class JWTUtils { private String secret_key = "sample"; private Algorithm AL = Algorithm.HMAC512(secret_key); - private long lifetime = 30; + // 4 hours + private long lifetime = 14400; /*** * jwt 토큰 생성 @@ -33,18 +33,9 @@ public String generate(String username, Collection roles){ * @return */ public JWTVerifyResult verify(String token){ - try{ - DecodedJWT decode = JWT.require(AL).build().verify(token); - return JWTVerifyResult.builder() - .user(decode.getSubject()) - .status(true) - .build(); - }catch(JWTVerificationException ex) { - DecodedJWT decode = JWT.decode(token); - return JWTVerifyResult.builder() - .user(decode.getSubject()) - .status(false) - .build(); - } + DecodedJWT decode = JWT.require(AL).build().verify(token); + return JWTVerifyResult.builder() + .user(decode.getSubject()) + .build(); } } diff --git a/backend/src/main/java/com/infp/ciat/config/security/jwt/JWTVerifyResult.java b/backend/src/main/java/com/infp/ciat/config/security/jwt/JWTVerifyResult.java index 2e70d56..310bc24 100644 --- a/backend/src/main/java/com/infp/ciat/config/security/jwt/JWTVerifyResult.java +++ b/backend/src/main/java/com/infp/ciat/config/security/jwt/JWTVerifyResult.java @@ -1,27 +1,19 @@ package com.infp.ciat.config.security.jwt; import lombok.Builder; +import lombok.Getter; import lombok.NoArgsConstructor; /*** * JWT 유효성검사 결과 */ +@Getter @NoArgsConstructor public class JWTVerifyResult { private String user; - private boolean status; @Builder - public JWTVerifyResult(String user, boolean status) { + public JWTVerifyResult(String user) { this.user = user; - this.status = status; - } - - public String getUser() { - return user; - } - - public boolean isStatus() { - return status; } }