From 376db324bd6afc98d4766650546ee3aa89776fa7 Mon Sep 17 00:00:00 2001 From: ac-f Date: Mon, 14 Nov 2022 14:16:16 +0800 Subject: [PATCH] =?UTF-8?q?Added|=20=E6=96=B0=E5=A2=9Emigration=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 51 ++++++++++++++++--- migrations/V0.0.1.0.1__demo.sql | 7 +++ .../bigdata/advice/AuthControllerAdvice.java | 24 +++++++++ .../org/fycd/bigdata/pojo/ErrorMessage.java | 19 +++++++ .../bigdata/service/RefreshTokenService.java | 2 +- .../java/org/fycd/bigdata/utils/JwtUtils.java | 11 ++-- src/main/resources/application-dev.yml | 10 +++- src/main/resources/application-prod.yml | 10 +++- src/main/resources/application.yml | 2 +- 9 files changed, 119 insertions(+), 17 deletions(-) create mode 100644 migrations/V0.0.1.0.1__demo.sql create mode 100644 security-core/src/main/java/org/fycd/bigdata/advice/AuthControllerAdvice.java create mode 100644 security-core/src/main/java/org/fycd/bigdata/pojo/ErrorMessage.java diff --git a/build.gradle b/build.gradle index aa81044..df6b99d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,20 +1,30 @@ +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'org.jooq:jooq-codegen:3.6.1' + classpath 'org.flywaydb:flyway-core' + classpath "org.flywaydb:flyway-mysql:9.2.0" + } +} + plugins { id 'java' id 'org.springframework.boot' version '2.7.5' id 'io.spring.dependency-management' version '1.0.15.RELEASE' + id "org.flywaydb.flyway" version "8.5.13" } - - allprojects{ apply plugin: 'java' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group = 'org.fycd' - version = '0.0.1-SNAPSHOT' + version = '0.0.1' - sourceCompatibility = 17 - targetCompatibility = 17 + sourceCompatibility = 11 + targetCompatibility = 11 repositories { mavenCentral() } @@ -28,8 +38,6 @@ allprojects{ implementation 'org.springframework.boot:spring-boot-starter-jooq' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.flywaydb:flyway-core' - implementation 'org.flywaydb:flyway-mysql' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.h2database:h2' @@ -48,3 +56,32 @@ dependencies { implementation project(':security-core') } + +task migrateDB(type: org.flywaydb.gradle.task.FlywayMigrateTask) { + driver = 'org.mariadb.jdbc.Driver' + url = 'jdbc:mariadb://localhost:3306/fycd?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Taipei' + user = 'root' + password = 'roottoor' + locations = ['filesystem:migrations'] + target = 'latest' + baselineVersion = '0.0.1.0.1' + baselineOnMigrate = true + validateOnMigrate = true + outOfOrder = true + placeholderReplacement = false +} + +task cleanDB(type: org.flywaydb.gradle.task.FlywayCleanTask) { + cleanDisabled = false + driver = 'org.mariadb.jdbc.Driver' + url = 'jdbc:mariadb://localhost:3306/fycd?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Taipei' + user = 'root' + password = 'roottoor' + locations = ['filesystem:migrations'] + target = 'latest' + baselineVersion = '0.0.1.0.1' + baselineOnMigrate = true + validateOnMigrate = true + outOfOrder = true + placeholderReplacement = false +} diff --git a/migrations/V0.0.1.0.1__demo.sql b/migrations/V0.0.1.0.1__demo.sql new file mode 100644 index 0000000..098aad3 --- /dev/null +++ b/migrations/V0.0.1.0.1__demo.sql @@ -0,0 +1,7 @@ +CREATE TABLE demo_migration ( + value VARCHAR(25) NOT NULL, + PRIMARY KEY(value) +); + + +INSERT INTO demo_migration (value) VALUES ('AC demo'); \ No newline at end of file diff --git a/security-core/src/main/java/org/fycd/bigdata/advice/AuthControllerAdvice.java b/security-core/src/main/java/org/fycd/bigdata/advice/AuthControllerAdvice.java new file mode 100644 index 0000000..f1e3deb --- /dev/null +++ b/security-core/src/main/java/org/fycd/bigdata/advice/AuthControllerAdvice.java @@ -0,0 +1,24 @@ +package org.fycd.bigdata.advice; + +import org.fycd.bigdata.exception.TokenRefreshException; +import org.fycd.bigdata.pojo.ErrorMessage; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.WebRequest; + +import java.time.LocalDateTime; + +@RestControllerAdvice +public class AuthControllerAdvice { + @ExceptionHandler(value = TokenRefreshException.class) + @ResponseStatus(HttpStatus.FORBIDDEN) + public ErrorMessage handleTokenRefreshException(TokenRefreshException ex, WebRequest request) { + return new ErrorMessage( + HttpStatus.FORBIDDEN.value(), + LocalDateTime.now(), + ex.getMessage(), + request.getDescription(false)); + } +} diff --git a/security-core/src/main/java/org/fycd/bigdata/pojo/ErrorMessage.java b/security-core/src/main/java/org/fycd/bigdata/pojo/ErrorMessage.java new file mode 100644 index 0000000..e6425f1 --- /dev/null +++ b/security-core/src/main/java/org/fycd/bigdata/pojo/ErrorMessage.java @@ -0,0 +1,19 @@ +package org.fycd.bigdata.pojo; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class ErrorMessage { + private int statusCode; + private LocalDateTime timestamp; + private String message; + private String description; + public ErrorMessage (int statusCode, LocalDateTime timestamp, String message, String description) { + this.statusCode = statusCode; + this.timestamp = timestamp; + this.message = message; + this.description = description; + } +} diff --git a/security-core/src/main/java/org/fycd/bigdata/service/RefreshTokenService.java b/security-core/src/main/java/org/fycd/bigdata/service/RefreshTokenService.java index bd281e5..f7c2f0b 100644 --- a/security-core/src/main/java/org/fycd/bigdata/service/RefreshTokenService.java +++ b/security-core/src/main/java/org/fycd/bigdata/service/RefreshTokenService.java @@ -16,7 +16,7 @@ import java.util.UUID; @Service @RequiredArgsConstructor public class RefreshTokenService { - @Value("${app.security.jwtExpiration") + @Value("${app.security.jwtExpiration}") private Long refreshTokenDuration; private final UserDaoSub userDao; diff --git a/security-core/src/main/java/org/fycd/bigdata/utils/JwtUtils.java b/security-core/src/main/java/org/fycd/bigdata/utils/JwtUtils.java index 0a907b6..9ef09d4 100644 --- a/security-core/src/main/java/org/fycd/bigdata/utils/JwtUtils.java +++ b/security-core/src/main/java/org/fycd/bigdata/utils/JwtUtils.java @@ -3,11 +3,9 @@ package org.fycd.bigdata.utils; import io.jsonwebtoken.*; import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.SignatureException; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.fycd.bigdata.service.UserDetailsImpl; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import javax.xml.bind.DatatypeConverter; @@ -19,8 +17,8 @@ public class JwtUtils { @Value("${app.security.jwtSecret}") private String jwtSecret; - @Value("${app.security.jwtExpirationMs}") - private int jwtExpirationMs; + @Value("${app.security.jwtExpiration}") + private Long jwtExpiration; public String generateJwtToken(UserDetailsImpl userPrincipal) { @@ -29,13 +27,14 @@ public class JwtUtils { public String generateTokenFromUsername(String username) { return Jwts.builder().setSubject(username).setIssuedAt(new Date()) - .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs)).signWith(SignatureAlgorithm.HS512, jwtSecret) + .setExpiration(new Date((new Date()).getTime() + jwtExpiration)) + .signWith(Keys.hmacShaKeyFor(DatatypeConverter.parseBase64Binary(jwtSecret))) .compact(); } public boolean validateJwtToken(String authToken) { try { - Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken); + getUserNameFromJwtToken(authToken); return true; } catch (SignatureException e) { log.error("Invalid JWT signature: {}", e.getMessage()); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 1ae69ee..516f629 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,4 +1,12 @@ app: security: jwtSecret: asdnkqldwk;l!@NLKASd12inkasldlxv.,xcvmkasldkqwe - jwtExpiration: 86400000 \ No newline at end of file + jwtExpiration: 86400000 +spring: + datasource: + driver-class-name: org.mariadb.jdbc.Driver + url: jdbc:mariadb://localhost:3306/fycd?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Taipei + username: root + password: roottoor + jooq: + sql-dialect: mariadb diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 1ae69ee..b0084e4 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -1,4 +1,12 @@ app: security: jwtSecret: asdnkqldwk;l!@NLKASd12inkasldlxv.,xcvmkasldkqwe - jwtExpiration: 86400000 \ No newline at end of file + jwtExpiration: 86400000 +spring: + datasource: + driver-class-name: org.mariadb.jdbc.Driver + url: jdbc:mariadb://localhost:3306/fycd?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Taipei + username: root + password: roottoor + jooq: + sql-dialect: mariadb \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index caf4dfc..3d7808a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,3 +1,3 @@ spring: profiles: - active: dev \ No newline at end of file + active: dev