From 9c68d745cfc894d030d472223c7d0931a5a27fe3 Mon Sep 17 00:00:00 2001 From: hjun-park Date: Thu, 2 Dec 2021 21:40:10 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Chore:=20Interceptor=20=EA=B3=84=EC=B8=B5?= =?UTF-8?q?=20=EB=B0=8F=20Role=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sikhye/chabak/base/entity/BaseRole.java | 5 ++ .../interceptor/JwtAdminInterceptor.java | 47 ++++++++++++ .../interceptor/JwtMemberInterceptor.java | 41 ++++++++++ .../sikhye/chabak/interceptor/WebConfig.java | 42 +++++++++++ src/main/resources/logback-spring.xml | 74 +++++++++++++++++++ 5 files changed, 209 insertions(+) create mode 100644 src/main/java/com/sikhye/chabak/base/entity/BaseRole.java create mode 100644 src/main/java/com/sikhye/chabak/interceptor/JwtAdminInterceptor.java create mode 100644 src/main/java/com/sikhye/chabak/interceptor/JwtMemberInterceptor.java create mode 100644 src/main/java/com/sikhye/chabak/interceptor/WebConfig.java create mode 100644 src/main/resources/logback-spring.xml diff --git a/src/main/java/com/sikhye/chabak/base/entity/BaseRole.java b/src/main/java/com/sikhye/chabak/base/entity/BaseRole.java new file mode 100644 index 0000000..1251ca5 --- /dev/null +++ b/src/main/java/com/sikhye/chabak/base/entity/BaseRole.java @@ -0,0 +1,5 @@ +package com.sikhye.chabak.base.entity; + +public enum BaseRole { + ROLE_USER, ROLE_ADMIN +} diff --git a/src/main/java/com/sikhye/chabak/interceptor/JwtAdminInterceptor.java b/src/main/java/com/sikhye/chabak/interceptor/JwtAdminInterceptor.java new file mode 100644 index 0000000..21e711a --- /dev/null +++ b/src/main/java/com/sikhye/chabak/interceptor/JwtAdminInterceptor.java @@ -0,0 +1,47 @@ +package com.sikhye.chabak.interceptor; + +import com.sikhye.chabak.base.exception.BaseException; +import com.sikhye.chabak.utils.JwtTokenService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static com.sikhye.chabak.base.BaseResponseStatus.INVALID_USER_JWT; +import static com.sikhye.chabak.base.entity.BaseRole.ROLE_ADMIN; + +@Slf4j +@Component +public class JwtAdminInterceptor implements HandlerInterceptor { + + private final JwtTokenService jwtTokenService; + + public JwtAdminInterceptor(JwtTokenService jwtTokenService) { + this.jwtTokenService = jwtTokenService; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + String requestURI = request.getRequestURI(); + + // places에서 GET 방식이라면 Admin 기능이 아닌 Member도 사용 가능 + if (request.getMethod().equals("GET")) { + return true; + } + + log.info("인증 체크 인터셉터 실행 {}", requestURI); + + // 관리자 권한이 아닌 경우 api 요청 불가 + String memberRole = jwtTokenService.getMemberRole(); + + if (!memberRole.equals(ROLE_ADMIN.toString())) { + throw new BaseException(INVALID_USER_JWT); + } + + return true; + + } +} diff --git a/src/main/java/com/sikhye/chabak/interceptor/JwtMemberInterceptor.java b/src/main/java/com/sikhye/chabak/interceptor/JwtMemberInterceptor.java new file mode 100644 index 0000000..2b121a7 --- /dev/null +++ b/src/main/java/com/sikhye/chabak/interceptor/JwtMemberInterceptor.java @@ -0,0 +1,41 @@ +package com.sikhye.chabak.interceptor; + +import com.sikhye.chabak.base.exception.BaseException; +import com.sikhye.chabak.utils.JwtTokenService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static com.sikhye.chabak.base.BaseResponseStatus.EMPTY_JWT; + +@Slf4j +@Component +public class JwtMemberInterceptor implements HandlerInterceptor { + + private final JwtTokenService jwtTokenService; + + public JwtMemberInterceptor(JwtTokenService jwtTokenService) { + this.jwtTokenService = jwtTokenService; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + + String requestURI = request.getRequestURI(); + String accessToken = request.getHeader("X-ACCESS-TOKEN"); + + log.info("인증 체크 인터셉터 실행 {}", requestURI); + + if (accessToken == null || accessToken.isBlank()) { + log.info("미인증 JWT 요청"); + throw new BaseException(EMPTY_JWT); + } + + return true; + } + +} diff --git a/src/main/java/com/sikhye/chabak/interceptor/WebConfig.java b/src/main/java/com/sikhye/chabak/interceptor/WebConfig.java new file mode 100644 index 0000000..a45eab0 --- /dev/null +++ b/src/main/java/com/sikhye/chabak/interceptor/WebConfig.java @@ -0,0 +1,42 @@ +package com.sikhye.chabak.interceptor; + +import lombok.Builder; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + private final JwtMemberInterceptor jwtMemberInterceptor; + private final JwtAdminInterceptor jwtAdminInterceptor; + + @Builder + public WebConfig(JwtMemberInterceptor jwtMemberInterceptor, JwtAdminInterceptor jwtAdminInterceptor) { + this.jwtMemberInterceptor = jwtMemberInterceptor; + this.jwtAdminInterceptor = jwtAdminInterceptor; + } + + // 인터셉터 등록 + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(jwtMemberInterceptor) // 인터셉터 등록 + .order(1) // 인터셉터 호출 우선순위 + .addPathPatterns("/**") // 인터셉터 적용할 URI 패턴 + .excludePathPatterns("/error", "/members/**", "/auth/**"); // 인터셉터에서 제외할 URI 패턴 + + registry.addInterceptor(jwtAdminInterceptor) + .order(2) + .addPathPatterns("/places/**") + .excludePathPatterns("/places/comments/**"); + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("http://localhost:3000") + .allowedMethods("GET", "POST", "OPTIONS", "PUT", "PATCH"); + } + +} diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..78ce2c3 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + true + + %d{YYYY-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %highlight([File:%F]) %magenta([Line:%L]) - %msg%n + + + + + + + + + logs/app.log + + logs/app.%d{yyyy-MM-dd}.%i.gz + + 10MB + + 30 + + + %d{YYYY-mm-dd HH:mm:ss.SSS} %-5level [File:%F] [Func:%M] [Line:%L] [Message:%m] + + + + + logs/error.log + + ERROR + ACCEPT + DENY + + + logs/error-%d{yyyy-MM-dd}.%i.gz + + 10MB + + 30 + + + %d{YYYY-mm-dd HH:mm:ss.SSS} %-5level [File:%F] [Func:%M] [Line:%L] [Message:%m] + + + + + + + + + + + + + From cc4f0bb06d8a82672cf3e8c10bb3866fce6a20b9 Mon Sep 17 00:00:00 2001 From: hjun-park Date: Mon, 6 Dec 2021 11:42:30 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Chore:=20=EC=84=A4=EC=A0=95=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 +- build.gradle | 129 +++++++++++++------------ chabak-deploy.sh | 2 +- src/main/resources/application.tar.gpg | Bin 1403 -> 1344 bytes src/main/resources/application.yml | 17 +--- 5 files changed, 75 insertions(+), 79 deletions(-) diff --git a/.gitignore b/.gitignore index a1692f0..b52f2ea 100644 --- a/.gitignore +++ b/.gitignore @@ -38,10 +38,12 @@ out/ ### custom ### -application-aws.yml -application-credentials.yml +#application-aws.yml +#application-credentials.yml Secret.java application-prod.yml application*.tar application-*.gpg logs/ +application-infra.yml +application-dev.yml diff --git a/build.gradle b/build.gradle index 748208f..fd1c934 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,9 @@ plugins { - id 'org.springframework.boot' version '2.5.6' - id 'io.spring.dependency-management' version '1.0.11.RELEASE' - id 'java' - // querydsl - id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" + id 'org.springframework.boot' version '2.5.6' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' + // querydsl + id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.sikhye' @@ -11,86 +11,89 @@ version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } dependencies { - // mysql DB - runtimeOnly ('mysql:mysql-connector-java') //mysql8 + // mysql DB + runtimeOnly('mysql:mysql-connector-java') //mysql8 - // spring batch - implementation 'org.springframework.boot:spring-boot-starter-batch' - testImplementation 'org.springframework.batch:spring-batch-test' + // spring batch + implementation 'org.springframework.boot:spring-boot-starter-batch' + testImplementation 'org.springframework.batch:spring-batch-test' - // spring jpa - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + // spring jpa + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - // spring template - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - implementation 'org.springframework.boot:spring-boot-starter-web' + // spring template + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-web' - // Bean Validation - implementation 'org.springframework.boot:spring-boot-starter-validation' + // Bean Validation + implementation 'org.springframework.boot:spring-boot-starter-validation' - // Lombok - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' + // Lombok + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' - // spring boot starter - testImplementation 'org.springframework.boot:spring-boot-starter-test' + // spring boot starter + testImplementation 'org.springframework.boot:spring-boot-starter-test' - // Security, Authentication(JWT Token) - implementation('org.springframework.boot:spring-boot-starter-security:2.5.4') - implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.2' - implementation('org.springframework.boot:spring-boot-starter') + // Security, Authentication(JWT Token) + implementation('org.springframework.boot:spring-boot-starter-security:2.5.4') + implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.2' + implementation('org.springframework.boot:spring-boot-starter') - // Spring Security for OAuth2) - implementation('org.springframework.boot:spring-boot-starter-oauth2-client') - implementation('org.springframework.boot:spring-boot-starter-mustache') + // Spring Security for OAuth2) + implementation('org.springframework.boot:spring-boot-starter-oauth2-client') + implementation('org.springframework.boot:spring-boot-starter-mustache') - // related to test - implementation('org.springframework.boot:spring-boot-devtools') + // related to test + implementation('org.springframework.boot:spring-boot-devtools') - // for Crawling - implementation('org.jsoup:jsoup:1.14.1') + // for Crawling + implementation('org.jsoup:jsoup:1.14.1') - // p6spy - implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.8' + // p6spy + implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.8' - // querydsl - implementation 'com.querydsl:querydsl-jpa' + // querydsl + implementation 'com.querydsl:querydsl-jpa' - // AWS S3 - implementation platform('com.amazonaws:aws-java-sdk-bom:1.11.1000') - implementation 'com.amazonaws:aws-java-sdk-s3:1.12.111' + // AWS S3 + implementation platform('com.amazonaws:aws-java-sdk-bom:1.11.1000') + implementation 'com.amazonaws:aws-java-sdk-s3:1.12.111' - // AWS cloud starter aws - implementation('org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE') + // AWS cloud starter aws + implementation('org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE') - // index.html로 forwarding 하기 위함 - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + // index.html로 forwarding 하기 위함 + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - // @ConfigureProperties를 사용하기 위해 추가 - // configure 파일을 읽어들이기 위함 - annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" + // @ConfigureProperties를 사용하기 위해 추가 + // configure 파일을 읽어들이기 위함 + annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" - // 이메일 인증 - implementation 'org.springframework.boot:spring-boot-starter-mail' + // 이메일 인증 + implementation 'org.springframework.boot:spring-boot-starter-mail' - // spring redis - implementation 'org.springframework.boot:spring-boot-starter-data-redis' + // spring redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + + // 로그 처리 시 조건 추가 + implementation 'org.codehaus.janino:janino:3.0.12' } test { - useJUnitPlatform() + useJUnitPlatform() } // ========================================== @@ -100,21 +103,21 @@ test { def querydslDir = "$buildDir/generated/querydsl" querydsl { - jpa = true - querydslSourcesDir = querydslDir + jpa = true + querydslSourcesDir = querydslDir } sourceSets { - main.java.srcDir querydslDir + main.java.srcDir querydslDir } configurations { - querydsl.extendsFrom compileClasspath + querydsl.extendsFrom compileClasspath } compileQuerydsl { - options.annotationProcessorPath = configurations.querydsl + options.annotationProcessorPath = configurations.querydsl } //querydsl 추가 끝 /** * comileQuerydsl.doFirst 추가 */ compileQuerydsl.doFirst { - if(file(querydslDir).exists() ) - delete(file(querydslDir)) + if (file(querydslDir).exists()) + delete(file(querydslDir)) } diff --git a/chabak-deploy.sh b/chabak-deploy.sh index 87e6d2d..02d8021 100644 --- a/chabak-deploy.sh +++ b/chabak-deploy.sh @@ -24,4 +24,4 @@ fi echo "> $JAR_PATH 배포" #nohup java -jar $JAR_PATH > /dev/null 2> /dev/null < /dev/null & #code deploy에 출력이 되기 때문에 nohup.out 파일을 사용해야 한다. -nohup java -jar $JAR_PATH > $REPOSITORY/nohup.out 2>&1 & +nohup java -jar -Dspring.profiles.active=prod $JAR_PATH > $REPOSITORY/nohup.out 2>&1 & diff --git a/src/main/resources/application.tar.gpg b/src/main/resources/application.tar.gpg index e8820360df83506a6dae41b39088a6ddb09f0dee..91ece9ea2fc726ce6c8a5e9a79307d814cc14e61 100644 GIT binary patch literal 1344 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 Date: Mon, 6 Dec 2021 11:43:17 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Chore:=20JWT,=20=EC=9D=B8=ED=84=B0=EC=85=89?= =?UTF-8?q?=ED=84=B0,=20logback=20=EC=84=A4=EC=A0=95=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interceptor/JwtAdminInterceptor.java | 26 +++++----- .../interceptor/JwtMemberInterceptor.java | 25 +++++----- .../sikhye/chabak/interceptor/WebConfig.java | 2 - .../sikhye/chabak/utils/JwtTokenProvider.java | 44 +++++++++-------- .../sikhye/chabak/utils/JwtTokenService.java | 32 ++++++------ .../com/sikhye/chabak/utils/JwtValue.java | 9 ++++ src/main/resources/logback-dev.properties | 4 ++ src/main/resources/logback-prod.properties | 4 ++ src/main/resources/logback-spring.xml | 49 ++++++++----------- 9 files changed, 105 insertions(+), 90 deletions(-) create mode 100644 src/main/java/com/sikhye/chabak/utils/JwtValue.java create mode 100644 src/main/resources/logback-dev.properties create mode 100644 src/main/resources/logback-prod.properties diff --git a/src/main/java/com/sikhye/chabak/interceptor/JwtAdminInterceptor.java b/src/main/java/com/sikhye/chabak/interceptor/JwtAdminInterceptor.java index 21e711a..98f5572 100644 --- a/src/main/java/com/sikhye/chabak/interceptor/JwtAdminInterceptor.java +++ b/src/main/java/com/sikhye/chabak/interceptor/JwtAdminInterceptor.java @@ -1,16 +1,19 @@ package com.sikhye.chabak.interceptor; -import com.sikhye.chabak.base.exception.BaseException; -import com.sikhye.chabak.utils.JwtTokenService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; +import static com.sikhye.chabak.base.BaseResponseStatus.*; +import static com.sikhye.chabak.base.entity.BaseRole.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import static com.sikhye.chabak.base.BaseResponseStatus.INVALID_USER_JWT; -import static com.sikhye.chabak.base.entity.BaseRole.ROLE_ADMIN; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import com.sikhye.chabak.base.entity.BaseRole; +import com.sikhye.chabak.base.exception.BaseException; +import com.sikhye.chabak.utils.JwtTokenService; + +import lombok.extern.slf4j.Slf4j; @Slf4j @Component @@ -23,8 +26,9 @@ public JwtAdminInterceptor(JwtTokenService jwtTokenService) { } @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, - Object handler) throws Exception { + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws + Exception { + String requestURI = request.getRequestURI(); // places에서 GET 방식이라면 Admin 기능이 아닌 Member도 사용 가능 @@ -35,9 +39,9 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons log.info("인증 체크 인터셉터 실행 {}", requestURI); // 관리자 권한이 아닌 경우 api 요청 불가 - String memberRole = jwtTokenService.getMemberRole(); + BaseRole memberRole = jwtTokenService.getMemberRole(); - if (!memberRole.equals(ROLE_ADMIN.toString())) { + if (!memberRole.equals(ROLE_ADMIN)) { throw new BaseException(INVALID_USER_JWT); } diff --git a/src/main/java/com/sikhye/chabak/interceptor/JwtMemberInterceptor.java b/src/main/java/com/sikhye/chabak/interceptor/JwtMemberInterceptor.java index 2b121a7..5b2ca6c 100644 --- a/src/main/java/com/sikhye/chabak/interceptor/JwtMemberInterceptor.java +++ b/src/main/java/com/sikhye/chabak/interceptor/JwtMemberInterceptor.java @@ -1,32 +1,29 @@ package com.sikhye.chabak.interceptor; -import com.sikhye.chabak.base.exception.BaseException; -import com.sikhye.chabak.utils.JwtTokenService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; +import static com.sikhye.chabak.base.BaseResponseStatus.*; +import static com.sikhye.chabak.utils.JwtValue.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import static com.sikhye.chabak.base.BaseResponseStatus.EMPTY_JWT; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import com.sikhye.chabak.base.exception.BaseException; + +import lombok.extern.slf4j.Slf4j; @Slf4j @Component public class JwtMemberInterceptor implements HandlerInterceptor { - private final JwtTokenService jwtTokenService; - - public JwtMemberInterceptor(JwtTokenService jwtTokenService) { - this.jwtTokenService = jwtTokenService; - } - @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, - Object handler) throws Exception { + Object handler) throws Exception { String requestURI = request.getRequestURI(); - String accessToken = request.getHeader("X-ACCESS-TOKEN"); + log.info("토큰명 : {}", X_ACCESS_TOKEN.toString()); + String accessToken = request.getHeader(X_ACCESS_TOKEN.toString()); log.info("인증 체크 인터셉터 실행 {}", requestURI); diff --git a/src/main/java/com/sikhye/chabak/interceptor/WebConfig.java b/src/main/java/com/sikhye/chabak/interceptor/WebConfig.java index a45eab0..281c97e 100644 --- a/src/main/java/com/sikhye/chabak/interceptor/WebConfig.java +++ b/src/main/java/com/sikhye/chabak/interceptor/WebConfig.java @@ -1,6 +1,5 @@ package com.sikhye.chabak.interceptor; -import lombok.Builder; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -12,7 +11,6 @@ public class WebConfig implements WebMvcConfigurer { private final JwtMemberInterceptor jwtMemberInterceptor; private final JwtAdminInterceptor jwtAdminInterceptor; - @Builder public WebConfig(JwtMemberInterceptor jwtMemberInterceptor, JwtAdminInterceptor jwtAdminInterceptor) { this.jwtMemberInterceptor = jwtMemberInterceptor; this.jwtAdminInterceptor = jwtAdminInterceptor; diff --git a/src/main/java/com/sikhye/chabak/utils/JwtTokenProvider.java b/src/main/java/com/sikhye/chabak/utils/JwtTokenProvider.java index 96c55b3..db2fce5 100644 --- a/src/main/java/com/sikhye/chabak/utils/JwtTokenProvider.java +++ b/src/main/java/com/sikhye/chabak/utils/JwtTokenProvider.java @@ -1,15 +1,19 @@ package com.sikhye.chabak.utils; +import static com.sikhye.chabak.utils.JwtValue.*; + +import java.util.Date; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletRequest; -import java.util.Date; -import java.util.List; @Component public class JwtTokenProvider { @@ -21,10 +25,10 @@ public class JwtTokenProvider { private final long tokenValidTime = 30 * 60 * 1000L; // 객체 초기화, secretKey를 Base64로 인코딩한다. -// @PostConstruct -// protected void init() { -// secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); -// } + // @PostConstruct + // protected void init() { + // secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); + // } // JWT 토큰 생성 public String createToken(String userPk, List roles) { @@ -40,20 +44,20 @@ public String createToken(String userPk, List roles) { .compact(); } -// // JWT 토큰에서 인증 정보 조회 -// public Authentication getAuthentication(String token) { -// UserDetails userDetails = userDetailsService.loadUserByUsername(this.getUserPk(token)); -// return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); -// } + // // JWT 토큰에서 인증 정보 조회 + // public Authentication getAuthentication(String token) { + // UserDetails userDetails = userDetailsService.loadUserByUsername(this.getUserPk(token)); + // return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); + // } -// // 토큰에서 회원 정보 추출 -// public String getUserPk(String token) { -// return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); -// } + // // 토큰에서 회원 정보 추출 + // public String getUserPk(String token) { + // return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); + // } // Request의 Header에서 token 값을 가져옵니다. "X-ACCESS-TOKEN" : "TOKEN값' public String resolveToken(HttpServletRequest request) { - return request.getHeader("X-ACCESS-TOKEN"); + return request.getHeader(X_ACCESS_TOKEN.toString()); } // 토큰의 유효성 + 만료일자 확인 diff --git a/src/main/java/com/sikhye/chabak/utils/JwtTokenService.java b/src/main/java/com/sikhye/chabak/utils/JwtTokenService.java index 47bd412..8235eb3 100644 --- a/src/main/java/com/sikhye/chabak/utils/JwtTokenService.java +++ b/src/main/java/com/sikhye/chabak/utils/JwtTokenService.java @@ -1,21 +1,24 @@ package com.sikhye.chabak.utils; -import com.sikhye.chabak.base.entity.BaseRole; -import com.sikhye.chabak.base.exception.BaseException; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; +import static com.sikhye.chabak.base.BaseResponseStatus.*; +import static com.sikhye.chabak.utils.JwtValue.*; + +import java.util.Date; + +import javax.servlet.http.HttpServletRequest; + import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import javax.servlet.http.HttpServletRequest; -import java.util.Date; +import com.sikhye.chabak.base.entity.BaseRole; +import com.sikhye.chabak.base.exception.BaseException; -import static com.sikhye.chabak.base.BaseResponseStatus.EMPTY_JWT; -import static com.sikhye.chabak.base.BaseResponseStatus.INVALID_JWT; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; @Service public class JwtTokenService { @@ -23,7 +26,6 @@ public class JwtTokenService { @Value("${secret.JWT_SECRET_KEY}") private String JWT_SECRET_KEY; - /* JWT 생성 @param userIdx @@ -46,8 +48,8 @@ public String createJwt(Long memberId, BaseRole role) { @return String */ public String getJwt() { - HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); - return request.getHeader("X-ACCESS-TOKEN"); + HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest(); + return request.getHeader(X_ACCESS_TOKEN.toString()); } /* @@ -55,7 +57,7 @@ public String getJwt() { @return String @throws BaseException */ - public String getMemberRole() throws BaseException { + public BaseRole getMemberRole() throws BaseException { //1. JWT 추출 String accessToken = getJwt(); if (accessToken == null || accessToken.length() == 0) { @@ -74,7 +76,7 @@ public String getMemberRole() throws BaseException { // 3. userIdx 추출 // ptpt: Object To Long - return String.valueOf(claims.getBody().get("role")); + return BaseRole.valueOf(String.valueOf(claims.getBody().get("role"))); } /* diff --git a/src/main/java/com/sikhye/chabak/utils/JwtValue.java b/src/main/java/com/sikhye/chabak/utils/JwtValue.java new file mode 100644 index 0000000..d56fc5f --- /dev/null +++ b/src/main/java/com/sikhye/chabak/utils/JwtValue.java @@ -0,0 +1,9 @@ +package com.sikhye.chabak.utils; + +public enum JwtValue { + X_ACCESS_TOKEN; + + public String toString() { + return name().replaceAll("_", "-"); + } +} diff --git a/src/main/resources/logback-dev.properties b/src/main/resources/logback-dev.properties new file mode 100644 index 0000000..40752f7 --- /dev/null +++ b/src/main/resources/logback-dev.properties @@ -0,0 +1,4 @@ +#logback +log.config.mode=dev +# log path +log.config.path=logs diff --git a/src/main/resources/logback-prod.properties b/src/main/resources/logback-prod.properties new file mode 100644 index 0000000..95a90b6 --- /dev/null +++ b/src/main/resources/logback-prod.properties @@ -0,0 +1,4 @@ +#logback +log.config.mode=prod +# log path +log.config.path=/var/log/chabak diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 78ce2c3..ae0eace 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -2,22 +2,7 @@ - - - - - - - - - - - - - - - - + true @@ -25,12 +10,10 @@ - - - + - logs/app.log + ${log.config.path}/app.log logs/app.%d{yyyy-MM-dd}.%i.gz @@ -44,7 +27,7 @@ - logs/error.log + ${log.config.path}/error.log ERROR ACCEPT @@ -62,13 +45,23 @@ - - - + + + + + + + + + - - - - + + + + + + + +