mirror of
https://github.com/RemainderTime/spring-boot-base-demo.git
synced 2026-06-10 03:57:41 +08:00
refactor(project): 重构项目配置和异常处理机制
- 更新 Docker Compose 配置从版本 1 到 3.8,并修改服务构建方式 - 将异常处理中的 ResponseCode 替换为 SystemStatus 枚举 - 统一全局异常处理器返回类型为 RetObj,替换原有的 GenericResponse - 修复 JWT 工具类中的空指针判断逻辑错误 - 优化 RSA 加密工具类,使用 Java 自带 Base64 实现替代 Apache 工具类 - 添加 Spring Security 密码编码器支持,增强用户密码安全性 - 完善日志配置文件,增加多种环境的日志输出策略 - 优化 Dockerfile 使用 JDK 17 环境并改进构建参数配置
This commit is contained in:
29
Dockerfile
29
Dockerfile
@@ -1,22 +1,17 @@
|
|||||||
# java8运行环境
|
# 使用 JDK 17 轻量级运行环境
|
||||||
FROM openjdk:8-jdk-alpine
|
FROM eclipse-temurin:17-jre-alpine
|
||||||
# 作者名称
|
|
||||||
MAINTAINER xiongfeng
|
# 作者信息
|
||||||
|
LABEL maintainer="xiongfeng"
|
||||||
|
|
||||||
# 切换工作目录
|
# 切换工作目录
|
||||||
WORKDIR /root/java
|
WORKDIR /root/java
|
||||||
|
|
||||||
#1. coding自动化部署
|
# 将编译好的 jar 包复制到容器中,避免硬编码包名版本号
|
||||||
#COPY target/*.jar app.jar
|
COPY target/*.jar app.jar
|
||||||
## 暴露端口8080
|
|
||||||
##EXPOSE 8080
|
|
||||||
## 运行命令
|
|
||||||
#ENTRYPOINT ["java","-Djava.security.egd=file:/dev/urandom","-Dfile.encoding=UTF-8","-Duser.timezone=Asia/Shanghai","-XX:MaxDirectMemorySize=1024m","-XX:MetaspaceSize=256m","-XX:MaxMetaspaceSize=512m","-XX:MaxRAMPercentage=80.0","-jar","app.jar"]
|
|
||||||
|
|
||||||
#2. 手动部署项目到docker环境中
|
# 暴露端口 8089 (对齐 application.yml)
|
||||||
# 添加demo-start-1.0.0.jar文件到docker环境内
|
EXPOSE 8089
|
||||||
ADD xf-boot-base-1.0.1.jar /root/java/xf-boot-base-1.0.1.jar
|
|
||||||
## 暴露端口8080
|
# 运行命令,加入垃圾回收和内存优化参数,以及时区与字符编码设置
|
||||||
#EXPOSE 8080
|
ENTRYPOINT ["java", "-server", "-Xms512m", "-Xmx512m", "-Dfile.encoding=UTF-8", "-Duser.timezone=Asia/Shanghai", "-jar", "app.jar"]
|
||||||
## 运行命令
|
|
||||||
ENTRYPOINT ["java", "-server", "-Xms512m", "-Xmx512m", "-jar", "/root/java/xf-boot-base-1.0.1.jar"]
|
|
||||||
|
|||||||
4
pom.xml
4
pom.xml
@@ -90,6 +90,10 @@
|
|||||||
<artifactId>java-jwt</artifactId>
|
<artifactId>java-jwt</artifactId>
|
||||||
<version>${jwt.version}</version>
|
<version>${jwt.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-crypto</artifactId>
|
||||||
|
</dependency>
|
||||||
<!--redis连接池需要依赖-->
|
<!--redis连接池需要依赖-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
public enum SystemStatus {
|
public enum SystemStatus {
|
||||||
|
|
||||||
SUSSES(200, "请求成功"),
|
SUCCESS(200, "请求成功"),
|
||||||
UNAVAILABILITY(401, "token无效"),
|
USER_INPUT_ERROR(400, "参数或用户输入错误"),
|
||||||
|
UNAUTHORIZED(401, "token无效"),
|
||||||
|
FORBIDDEN(403, "禁止访问"),
|
||||||
|
TOO_FREQUENT_VISIT(429, "访问太频繁,请休息一会儿"),
|
||||||
ERROR(500, "系统异常")
|
ERROR(500, "系统异常")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package cn.xf.basedemo.common.exception;
|
package cn.xf.basedemo.common.exception;
|
||||||
|
|
||||||
|
import cn.xf.basedemo.common.enums.SystemStatus;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,29 +11,29 @@ import lombok.Getter;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public class BusinessException extends RuntimeException{
|
public class BusinessException extends RuntimeException{
|
||||||
private final ResponseCode code;
|
private final SystemStatus status;
|
||||||
|
|
||||||
public BusinessException() {
|
public BusinessException() {
|
||||||
super(String.format("%s", ResponseCode.INTERNAL_ERROR.getMessage()));
|
super(String.format("%s", SystemStatus.ERROR.getErrorMessage()));
|
||||||
this.code = ResponseCode.INTERNAL_ERROR;
|
this.status = SystemStatus.ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BusinessException(Throwable e) {
|
public BusinessException(Throwable e) {
|
||||||
super(e);
|
super(e);
|
||||||
this.code = ResponseCode.INTERNAL_ERROR;
|
this.status = SystemStatus.ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BusinessException(String msg) {
|
public BusinessException(String msg) {
|
||||||
this(ResponseCode.INTERNAL_ERROR, msg);
|
this(SystemStatus.ERROR, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BusinessException(ResponseCode code) {
|
public BusinessException(SystemStatus status) {
|
||||||
super(String.format("%s", code.getMessage()));
|
super(String.format("%s", status.getErrorMessage()));
|
||||||
this.code = code;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BusinessException(ResponseCode code, String msg) {
|
public BusinessException(SystemStatus status, String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
this.code = code;
|
this.status = status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package cn.xf.basedemo.common.exception;
|
package cn.xf.basedemo.common.exception;
|
||||||
|
|
||||||
|
import cn.xf.basedemo.common.enums.SystemStatus;
|
||||||
|
import cn.xf.basedemo.common.model.RetObj;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.validation.BindException;
|
import org.springframework.validation.BindException;
|
||||||
@@ -28,9 +30,9 @@ public class GlobalExceptionHandler {
|
|||||||
*/
|
*/
|
||||||
@ExceptionHandler(LoginException.class)
|
@ExceptionHandler(LoginException.class)
|
||||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||||
public GenericResponse<Void> handleLoginException(LoginException e, HttpServletRequest request) {
|
public RetObj<Void> handleLoginException(LoginException e, HttpServletRequest request) {
|
||||||
log.warn("认证失败 [URL:{}]: code={}, message={}", request.getRequestURI(), e.getCode(), e.getMessage());
|
log.warn("认证失败 [URL:{}]: code={}, message={}", request.getRequestURI(), e.getStatus().getCode(), e.getMessage());
|
||||||
return new GenericResponse<>(e.getCode(), null, e.getMessage());
|
return new RetObj<>(e.getStatus().getCode(), e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,9 +40,9 @@ public class GlobalExceptionHandler {
|
|||||||
*/
|
*/
|
||||||
@ExceptionHandler(BusinessException.class)
|
@ExceptionHandler(BusinessException.class)
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST) // 或者使用 HttpStatus.OK,根据前端约定
|
@ResponseStatus(HttpStatus.BAD_REQUEST) // 或者使用 HttpStatus.OK,根据前端约定
|
||||||
public GenericResponse<Void> handleBusinessException(BusinessException e, HttpServletRequest request) {
|
public RetObj<Void> handleBusinessException(BusinessException e, HttpServletRequest request) {
|
||||||
log.warn("业务异常 [URL:{}]: code={}, message={}", request.getRequestURI(), e.getCode(), e.getMessage());
|
log.warn("业务异常 [URL:{}]: code={}, message={}", request.getRequestURI(), e.getStatus().getCode(), e.getMessage());
|
||||||
return new GenericResponse<>(e.getCode(), null, e.getMessage());
|
return new RetObj<>(e.getStatus().getCode(), e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +50,7 @@ public class GlobalExceptionHandler {
|
|||||||
*/
|
*/
|
||||||
@ExceptionHandler({ MethodArgumentNotValidException.class, BindException.class })
|
@ExceptionHandler({ MethodArgumentNotValidException.class, BindException.class })
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
public GenericResponse<Void> handleValidationException(Exception e, HttpServletRequest request) {
|
public RetObj<Void> handleValidationException(Exception e, HttpServletRequest request) {
|
||||||
BindingResult bindingResult = null;
|
BindingResult bindingResult = null;
|
||||||
if (e instanceof MethodArgumentNotValidException) {
|
if (e instanceof MethodArgumentNotValidException) {
|
||||||
bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
|
bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
|
||||||
@@ -64,7 +66,7 @@ public class GlobalExceptionHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.warn("参数校验失败 [URL:{}]: {}", request.getRequestURI(), errorMsg);
|
log.warn("参数校验失败 [URL:{}]: {}", request.getRequestURI(), errorMsg);
|
||||||
return new GenericResponse<>(ResponseCode.USER_INPUT_ERROR.getCode(), null, errorMsg);
|
return new RetObj<>(SystemStatus.USER_INPUT_ERROR.getCode(), errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,9 +74,9 @@ public class GlobalExceptionHandler {
|
|||||||
*/
|
*/
|
||||||
@ExceptionHandler(Exception.class)
|
@ExceptionHandler(Exception.class)
|
||||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
public GenericResponse<Void> handleSystemException(Exception e, HttpServletRequest request) {
|
public RetObj<Void> handleSystemException(Exception e, HttpServletRequest request) {
|
||||||
// 生产级关键点:必须记录异常堆栈,否则无法排查 BUG
|
// 生产级关键点:必须记录异常堆栈,否则无法排查 BUG
|
||||||
log.error("系统发生未知异常 [URL:{}]", request.getRequestURI(), e);
|
log.error("系统发生未知异常 [URL:{}]", request.getRequestURI(), e);
|
||||||
return new GenericResponse<>(500, null, "系统内部繁忙,请稍后再试");
|
return new RetObj<>(SystemStatus.ERROR.getCode(), "系统内部繁忙,请稍后再试");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package cn.xf.basedemo.common.exception;
|
package cn.xf.basedemo.common.exception;
|
||||||
|
|
||||||
|
import cn.xf.basedemo.common.enums.SystemStatus;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,30 +12,30 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
public class LoginException extends RuntimeException{
|
public class LoginException extends RuntimeException{
|
||||||
|
|
||||||
private final ResponseCode code;
|
private final SystemStatus status;
|
||||||
|
|
||||||
public LoginException() {
|
public LoginException() {
|
||||||
super(String.format("%s", ResponseCode.AUTHENTICATION_NEEDED.getMessage()));
|
super(String.format("%s", SystemStatus.UNAUTHORIZED.getErrorMessage()));
|
||||||
this.code = ResponseCode.AUTHENTICATION_NEEDED;
|
this.status = SystemStatus.UNAUTHORIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoginException(Throwable e) {
|
public LoginException(Throwable e) {
|
||||||
super(e);
|
super(e);
|
||||||
this.code = ResponseCode.AUTHENTICATION_NEEDED;
|
this.status = SystemStatus.UNAUTHORIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoginException(String msg) {
|
public LoginException(String msg) {
|
||||||
this(ResponseCode.AUTHENTICATION_NEEDED, msg);
|
this(SystemStatus.UNAUTHORIZED, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoginException(ResponseCode code) {
|
public LoginException(SystemStatus status) {
|
||||||
super(String.format("%s", code.getMessage()));
|
super(String.format("%s", status.getErrorMessage()));
|
||||||
this.code = code;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoginException(ResponseCode code, String msg) {
|
public LoginException(SystemStatus status, String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
this.code = code;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,20 +46,20 @@ public class RetObj<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <T> RetObj<T> success() {
|
public static <T> RetObj<T> success() {
|
||||||
return new RetObj(SystemStatus.SUSSES);
|
return new RetObj<>(SystemStatus.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> RetObj<T> success(T data) {
|
public static <T> RetObj<T> success(T data) {
|
||||||
return new RetObj(SystemStatus.SUSSES, data);
|
return new RetObj<>(SystemStatus.SUCCESS, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static <T> RetObj<T> error(SystemStatus status) {
|
public static <T> RetObj<T> error(SystemStatus status) {
|
||||||
return new RetObj(status);
|
return new RetObj<>(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> RetObj<T> error(String errorMsg) {
|
public static <T> RetObj<T> error(String errorMsg) {
|
||||||
return new RetObj(SystemStatus.ERROR.getCode(), errorMsg);
|
return new RetObj<>(SystemStatus.ERROR.getCode(), errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class JwtTokenUtils {
|
|||||||
*/
|
*/
|
||||||
public static Integer getUserId(String token) {
|
public static Integer getUserId(String token) {
|
||||||
Map<String, Claim> claims = verifyToken(token);
|
Map<String, Claim> claims = verifyToken(token);
|
||||||
if (claims != null) {
|
if (claims == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package cn.xf.basedemo.common.utils;
|
package cn.xf.basedemo.common.utils;
|
||||||
|
|
||||||
import org.apache.tomcat.util.codec.binary.Base64;
|
|
||||||
import org.apache.tomcat.util.http.fileupload.IOUtils;
|
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
@@ -11,6 +8,7 @@ import java.security.interfaces.RSAPublicKey;
|
|||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -20,7 +18,7 @@ import java.util.Map;
|
|||||||
* @description: 加密工具类
|
* @description: 加密工具类
|
||||||
* @author: xiongfeng
|
* @author: xiongfeng
|
||||||
* @create: 2022-06-20 10:37
|
* @create: 2022-06-20 10:37
|
||||||
**/
|
* **/
|
||||||
public class RSAUtils {
|
public class RSAUtils {
|
||||||
|
|
||||||
//算法类型
|
//算法类型
|
||||||
@@ -49,10 +47,10 @@ public class RSAUtils {
|
|||||||
kpg.initialize(ENCRYPT_SIZE);
|
kpg.initialize(ENCRYPT_SIZE);
|
||||||
KeyPair keyPair = kpg.generateKeyPair();
|
KeyPair keyPair = kpg.generateKeyPair();
|
||||||
PublicKey aPublic = keyPair.getPublic();
|
PublicKey aPublic = keyPair.getPublic();
|
||||||
String publicKey = Base64.encodeBase64URLSafeString(aPublic.getEncoded());
|
String publicKey = Base64.getUrlEncoder().withoutPadding().encodeToString(aPublic.getEncoded());
|
||||||
|
|
||||||
PrivateKey aPrivate = keyPair.getPrivate();
|
PrivateKey aPrivate = keyPair.getPrivate();
|
||||||
String privateKey = Base64.encodeBase64URLSafeString(aPrivate.getEncoded());
|
String privateKey = Base64.getUrlEncoder().withoutPadding().encodeToString(aPrivate.getEncoded());
|
||||||
|
|
||||||
Map<String, String> map = new HashMap<>();
|
Map<String, String> map = new HashMap<>();
|
||||||
|
|
||||||
@@ -73,7 +71,7 @@ public class RSAUtils {
|
|||||||
public static RSAPublicKey getPublicKey(String publicKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
public static RSAPublicKey getPublicKey(String publicKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
// 通过X509编码的Key指令获得公钥对象
|
// 通过X509编码的Key指令获得公钥对象
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
||||||
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64URLSafe(publicKeyStr));
|
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.getUrlDecoder().decode(publicKeyStr));
|
||||||
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
|
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
@@ -89,7 +87,7 @@ public class RSAUtils {
|
|||||||
public static RSAPrivateKey getPrivateKey(String privateKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
public static RSAPrivateKey getPrivateKey(String privateKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
||||||
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64URLSafe(privateKeyStr));
|
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(privateKeyStr));
|
||||||
RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);
|
RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);
|
||||||
return privateKey;
|
return privateKey;
|
||||||
}
|
}
|
||||||
@@ -109,8 +107,7 @@ public class RSAUtils {
|
|||||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
|
|
||||||
byte[] bytes = cipher.doFinal(data.getBytes());
|
byte[] bytes = cipher.doFinal(data.getBytes());
|
||||||
return Base64.encodeBase64URLSafeString(bytes);
|
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
|
||||||
// return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
@@ -121,9 +118,7 @@ public class RSAUtils {
|
|||||||
Cipher cipher = Cipher.getInstance(RSA);
|
Cipher cipher = Cipher.getInstance(RSA);
|
||||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
|
|
||||||
// byte[] bytes = cipher.doFinal(Base64.decodeBase64(data.getBytes(CHARSET)));
|
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.getUrlDecoder().decode(data.getBytes(CHARSET)), privateKey.getModulus().bitLength()), CHARSET);
|
||||||
// return new String(bytes);
|
|
||||||
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data.getBytes(CHARSET), 0, data.getBytes(CHARSET).length), privateKey.getModulus().bitLength()), CHARSET);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
|
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
|
||||||
}
|
}
|
||||||
@@ -137,11 +132,10 @@ public class RSAUtils {
|
|||||||
} else {
|
} else {
|
||||||
maxBlock = keySize / 8 - 11;
|
maxBlock = keySize / 8 - 11;
|
||||||
}
|
}
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
int offSet = 0;
|
int offSet = 0;
|
||||||
byte[] buff;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
try {
|
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||||
|
byte[] buff;
|
||||||
while (datas.length > offSet) {
|
while (datas.length > offSet) {
|
||||||
if (datas.length - offSet > maxBlock) {
|
if (datas.length - offSet > maxBlock) {
|
||||||
//可以调用以下的doFinal()方法完成加密或解密数据:
|
//可以调用以下的doFinal()方法完成加密或解密数据:
|
||||||
@@ -153,12 +147,10 @@ public class RSAUtils {
|
|||||||
i++;
|
i++;
|
||||||
offSet = i * maxBlock;
|
offSet = i * maxBlock;
|
||||||
}
|
}
|
||||||
|
return out.toByteArray();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
|
throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
|
||||||
}
|
}
|
||||||
byte[] resultDatas = out.toByteArray();
|
|
||||||
IOUtils.closeQuietly(out);
|
|
||||||
return resultDatas;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|||||||
@@ -52,9 +52,9 @@ public class RequestHeaderUtil {
|
|||||||
public static String getToken(HttpServletRequest request) {
|
public static String getToken(HttpServletRequest request) {
|
||||||
//登录处理
|
//登录处理
|
||||||
String token = request.getHeader("Authorization");
|
String token = request.getHeader("Authorization");
|
||||||
if (StringUtils.isEmpty(token))
|
if (!StringUtils.hasText(token))
|
||||||
token = request.getParameter("token");
|
token = request.getParameter("token");
|
||||||
if (StringUtils.isEmpty(token)) {
|
if (!StringUtils.hasText(token)) {
|
||||||
throw new LoginException("请先登录");
|
throw new LoginException("请先登录");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package cn.xf.basedemo.interceptor;
|
package cn.xf.basedemo.interceptor;
|
||||||
|
|
||||||
import cn.xf.basedemo.common.exception.LoginException;
|
import cn.xf.basedemo.common.exception.LoginException;
|
||||||
import cn.xf.basedemo.common.exception.ResponseCode;
|
import cn.xf.basedemo.common.enums.SystemStatus;
|
||||||
import cn.xf.basedemo.common.model.LoginUser;
|
import cn.xf.basedemo.common.model.LoginUser;
|
||||||
import cn.xf.basedemo.common.utils.ApplicationContextUtils;
|
import cn.xf.basedemo.common.utils.ApplicationContextUtils;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
@@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* @description:
|
* @description:
|
||||||
* @author: xiongfeng
|
* @author: xiongfeng
|
||||||
* @create: 2022-06-16 14:17
|
* @create: 2022-06-16 14:17
|
||||||
|
* @component
|
||||||
**/
|
**/
|
||||||
@Component
|
@Component
|
||||||
public class TokenInterceptor implements HandlerInterceptor {
|
public class TokenInterceptor implements HandlerInterceptor {
|
||||||
@@ -45,28 +46,28 @@ public class TokenInterceptor implements HandlerInterceptor {
|
|||||||
}
|
}
|
||||||
//登录处理
|
//登录处理
|
||||||
String token = request.getHeader("Authorization");
|
String token = request.getHeader("Authorization");
|
||||||
if (StringUtils.isEmpty(token))
|
if (!StringUtils.hasText(token))
|
||||||
token = request.getParameter("token");
|
token = request.getParameter("token");
|
||||||
if (StringUtils.isEmpty(token)) {
|
if (!StringUtils.hasText(token)) {
|
||||||
throw new LoginException("请先登录");
|
throw new LoginException("请先登录");
|
||||||
}else {
|
}else {
|
||||||
//验证token
|
//验证token
|
||||||
if (!token.startsWith("Bearer ")) {
|
if (!token.startsWith("Bearer ")) {
|
||||||
throw new LoginException(ResponseCode.USER_INPUT_ERROR);
|
throw new LoginException(SystemStatus.USER_INPUT_ERROR);
|
||||||
}
|
}
|
||||||
token = token.substring(7);
|
token = token.substring(7);
|
||||||
}
|
}
|
||||||
String value = (String) redisTemplate.opsForValue().get("token:" + token);
|
String value = (String) redisTemplate.opsForValue().get("token:" + token);
|
||||||
if (StringUtils.isEmpty(value)) {
|
if (!StringUtils.hasText(value)) {
|
||||||
throw new LoginException();
|
throw new LoginException();
|
||||||
}
|
}
|
||||||
JSONObject jsonObject = JSONObject.parseObject(value);
|
JSONObject jsonObject = JSONObject.parseObject(value);
|
||||||
//JSON对象转换成Java对象
|
//JSON对象转换成Java对象
|
||||||
LoginUser loginUserInfo = JSONObject.toJavaObject(jsonObject, LoginUser.class);
|
LoginUser loginUserInfo = JSONObject.toJavaObject(jsonObject, LoginUser.class);
|
||||||
if (loginUserInfo == null || loginUserInfo.getId() <= 0) {
|
if (loginUserInfo == null || loginUserInfo.getId() <= 0) {
|
||||||
throw new LoginException(ResponseCode.USER_INPUT_ERROR);
|
throw new LoginException(SystemStatus.USER_INPUT_ERROR);
|
||||||
}
|
}
|
||||||
redisTemplate.expire(token, 86700, TimeUnit.SECONDS);
|
redisTemplate.expire("token:" + token, 86700, TimeUnit.SECONDS);
|
||||||
|
|
||||||
//用户信息设置到上下文
|
//用户信息设置到上下文
|
||||||
SessionContext.getInstance().set(loginUserInfo);
|
SessionContext.getInstance().set(loginUserInfo);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@@ -46,10 +47,12 @@ public class UserServiceImpl implements UserService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RedisTemplate redisTemplate;
|
private RedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RetObj login(LoginInfoRes res) {
|
public RetObj login(LoginInfoRes res) {
|
||||||
|
|
||||||
if (Objects.isNull(res) || StringUtils.isEmpty(res.getEncryptedData())) {
|
if (Objects.isNull(res) || !StringUtils.hasText(res.getEncryptedData())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String loginJson = "";
|
String loginJson = "";
|
||||||
@@ -65,15 +68,14 @@ public class UserServiceImpl implements UserService {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return RetObj.error("账号或密码错误");
|
return RetObj.error("账号或密码错误");
|
||||||
}
|
}
|
||||||
if (!StringUtils.isEmpty(loginInfo.check())) {
|
if (StringUtils.hasText(loginInfo.check())) {
|
||||||
return RetObj.error(loginInfo.check());
|
return RetObj.error(loginInfo.check());
|
||||||
}
|
}
|
||||||
//校验登录账号密码
|
//校验登录账号密码
|
||||||
QueryWrapper queryWrapper = new QueryWrapper();
|
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
|
||||||
queryWrapper.eq("account", loginInfo.getAccount());
|
queryWrapper.eq("account", loginInfo.getAccount());
|
||||||
queryWrapper.eq("password", loginInfo.getPwd());
|
|
||||||
User user = userMapper.selectOne(queryWrapper);
|
User user = userMapper.selectOne(queryWrapper);
|
||||||
if (Objects.isNull(user)) {
|
if (Objects.isNull(user) || !passwordEncoder.matches(loginInfo.getPwd(), user.getPassword())) {
|
||||||
return RetObj.error("账号或密码错误");
|
return RetObj.error("账号或密码错误");
|
||||||
}
|
}
|
||||||
LoginUser loginUser = new LoginUser();
|
LoginUser loginUser = new LoginUser();
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
version: '1'
|
version: '3.8'
|
||||||
services:
|
services:
|
||||||
boot_docker_compose:
|
xf-boot-base:
|
||||||
image: remaindertime/boot_docker_compose:v1.0.0
|
build:
|
||||||
container_name: boot_docker_compose
|
context: ../../../
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: xf-boot-base
|
||||||
environment:
|
environment:
|
||||||
- SERVER_ADDRESS=120.48.109.209
|
- SERVER_ADDRESS=120.48.109.209
|
||||||
- MYSQL_NAME=root
|
- MYSQL_NAME=root
|
||||||
- MYSQL_PWD=123456
|
- MYSQL_PWD=123456
|
||||||
- REDIS_PWD=123456
|
- REDIS_PWD=123456
|
||||||
ports:
|
ports:
|
||||||
- 8090:8088
|
- 8089:8089
|
||||||
85
src/main/resources/logback-spring.xml
Normal file
85
src/main/resources/logback-spring.xml
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration scan="true" scanPeriod="60 seconds">
|
||||||
|
<contextName>xf-boot-base</contextName>
|
||||||
|
|
||||||
|
<property name="log_home" value="logs"/>
|
||||||
|
<property name="log_pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
|
||||||
|
|
||||||
|
<!-- 控制台输出 -->
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log_pattern}</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- Info本地日志 -->
|
||||||
|
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${log_home}/base-info.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${log_home}/base-%d{yyyy-MM-dd}-info.%i.log</fileNamePattern>
|
||||||
|
<maxFileSize>200MB</maxFileSize>
|
||||||
|
<maxHistory>30</maxHistory>
|
||||||
|
<totalSizeCap>10GB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log_pattern}</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>INFO</level>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- Error本地日志 -->
|
||||||
|
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${log_home}/base-error.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${log_home}/base-%d{yyyy-MM-dd}-error.%i.log</fileNamePattern>
|
||||||
|
<maxFileSize>200MB</maxFileSize>
|
||||||
|
<maxHistory>30</maxHistory>
|
||||||
|
<totalSizeCap>5GB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log_pattern}</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>ERROR</level>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- Logstash输出(动态读取配置) -->
|
||||||
|
<springProperty scope="context" name="logIps" source="logstash.ips" defaultValue="127.0.0.1:4560"/>
|
||||||
|
<springProperty scope="context" name="appName" source="spring.application.name" defaultValue="xf-boot-base"/>
|
||||||
|
|
||||||
|
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
|
||||||
|
<destination>${logIps}</destination>
|
||||||
|
<keepAliveDuration>5 minutes</keepAliveDuration>
|
||||||
|
<connectionTimeout>5 seconds</connectionTimeout>
|
||||||
|
<reconnectionDelay>30 seconds</reconnectionDelay>
|
||||||
|
<waitStrategyType>sleeping</waitStrategyType>
|
||||||
|
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
|
||||||
|
<customFields>{"host":"${HOSTNAME}", "app_name":"${appName}"}</customFields>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- 开发与本地环境 -->
|
||||||
|
<springProfile name="dev,local">
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
<appender-ref ref="INFO_FILE"/>
|
||||||
|
<appender-ref ref="ERROR_FILE"/>
|
||||||
|
</root>
|
||||||
|
</springProfile>
|
||||||
|
|
||||||
|
<!-- 测试与预发布/生产环境 -->
|
||||||
|
<springProfile name="pre,prod">
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
<appender-ref ref="INFO_FILE"/>
|
||||||
|
<appender-ref ref="ERROR_FILE"/>
|
||||||
|
<appender-ref ref="LOGSTASH"/>
|
||||||
|
</root>
|
||||||
|
</springProfile>
|
||||||
|
</configuration>
|
||||||
Reference in New Issue
Block a user