2.3.0版本

This commit is contained in:
zhangqinbin
2024-01-19 17:33:12 +08:00
parent c4e5b7a830
commit 5d1a6227e8
16 changed files with 1084 additions and 22 deletions

View File

@ -7,13 +7,13 @@
<parent>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-parent</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<relativePath>../mall-ebtp-cloud-parent</relativePath>
</parent>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-jpa-starter</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<name>mall-ebtp-cloud-jpa-starter</name>

View File

@ -8,13 +8,13 @@
<parent>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-parent</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<relativePath>../mall-ebtp-cloud-parent</relativePath>
</parent>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-kafka-starter</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<name>mall-ebtp-cloud-kafka-starter</name>
<dependencies>

View File

@ -7,12 +7,12 @@
<parent>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
</parent>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-parent</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>mall-ebtp-cloud-parent</name>
@ -24,22 +24,22 @@
<dependency>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-jpa-starter</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-kafka-starter</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.chinaunicom.mall.ebtp</groupId>
<artifactId>uboot-common</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.chinaunicom.mall.ebtp</groupId>
<artifactId>uboot-core</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
@ -48,6 +48,26 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.80</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>9.0.80</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -13,7 +13,7 @@
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>mall-ebtp-cloud</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-parent</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<relativePath>../mall-ebtp-cloud-parent</relativePath>
</parent>
<groupId>com.chinaunicom.mall.ebtp</groupId>
<artifactId>uboot-common</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<name>uboot-common</name>
<dependencies>

View File

@ -28,5 +28,38 @@ public class JasyptStarterConfiguration {
return encryptor;
}
public static String encryptStr(String encryptStr, String password) {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(password);
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
String enPw = encryptor.encrypt(encryptStr);
System.out.println("加密后:" + enPw);
String decrypt = encryptor.decrypt(enPw);
System.out.println("解密的字符串:" + decrypt);
return enPw;
}
public static void main(String[] args) {
// PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// SimpleStringPBEConfig config = new SimpleStringPBEConfig();
// config.setPassword("uniom-ebtp");
// config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
// config.setKeyObtentionIterations("1000");
// config.setPoolSize("1");
// config.setProviderName("SunJCE");
// config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
// config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
// config.setStringOutputType("base64");
// encryptor.setConfig(config);
// String decrypt = encryptor.decrypt("VwMRvAmu9rP0TGa1REZL5khiOOZtI47GoRJeHBN9LRDkJ+heZ4vXQ82/scobMGKW");
JasyptStarterConfiguration.encryptStr("ProdMall3_0531portal","uniom-ebtp");
}
}

View File

@ -15,8 +15,7 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.REMOTE_ACCESS_FAILURE;
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.TOKEN_EXPIRED;
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.*;
/**
* 通过实现EntryPoint接口自定义spring security异常返回
@ -42,6 +41,7 @@ public class UserAuthenticationEntryPoint implements AuthenticationEntryPoint {
response.setContentType(RESPONSE_CONTENT_TYPE);
String code = (String) request.getSession().getAttribute("code");// security filter 返回的自定义状态码
log.info("commence :"+code);
//未获取到token 且不在白名单
if (authException instanceof InsufficientAuthenticationException) {
code = REMOTE_ACCESS_FAILURE;
@ -67,6 +67,8 @@ public class UserAuthenticationEntryPoint implements AuthenticationEntryPoint {
return accessDenidedException(code, response);
case REMOTE_ACCESS_FAILURE:
return remoteTimeoutException(code, response);
case REMOTE_ACCESS_CHECK:
return remoteCheckException(code, response);
default:
return globalException(code, response);
}
@ -103,7 +105,21 @@ public class UserAuthenticationEntryPoint implements AuthenticationEntryPoint {
return map;
}
/**
* Token 远程认证服务超时
*
* @param code
* @return
*/
private Map<String, Object> remoteCheckException(String code, HttpServletResponse response) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
Map<String, Object> map = new HashMap<>();
map.put("code", code);
map.put("message", "无效请求");
return map;
}
/**
* @return
*/

View File

@ -9,6 +9,7 @@ public interface Constants {
public static final String TOKEN_PREFIX = "Bearer ";
public static final String CURRENT_ROLE_CODE = "currentRoleCode";
public static final String COOKIE_TOKEN_CODE = "mall3_token";
public static final String HEADER_CHECK_TOKEN = "Mall3Check";
public static final String REDIS_USER_KEY = "ebtp:user_cache:";
public static final String REDIS_USER_KEY_EXTEND = "ebtp:user_cache_extend";
public static final String USERS = "users";
@ -16,6 +17,7 @@ public interface Constants {
public static final String TOKEN_EXPIRED = "90401";
public static final String REMOTE_ACCESS_FAILURE = "90500";
public static final String REMOTE_ACCESS_CHECK = "90501";
String ACTUATOR_HEALTH = "actuator/health";
String ACTUATOR_PROMETHEUS = "actuator/prometheus";

View File

@ -0,0 +1,243 @@
package com.chinaunicom.mall.ebtp.cloud.security.starter.common;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> params = new HashMap<String, String[]>();
private byte[] body;
@SuppressWarnings("unchecked")
public ParameterRequestWrapper(HttpServletRequest request,String privateKey) {
// 将request交给父类以便于调用对应方法的时候将其输出
// 其实父亲类的实现方式和第一种new的方式类似
super(request);
String value = "";
try {
String method = request.getMethod();
String queryString = "";
if("GET".equals(method)){
queryString = request.getQueryString();
}else if("POST".equals(method)) {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
queryString = stringBuilder.toString();
}
}
log.info("----请求 queryString: "+queryString);
if(queryString!=null&&!"".equals(queryString)) {
//String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJOGd3FrZ3nB3VeBnD86hEfKqqEQqfZWPx6wg1w8dEMrP94PGsdPzviyxh9F2RA9Th3XfIuHLC7fQPQn8i6wHUBrLQqXt+zNjO0/ViDtjwaaLDKePhsWiggVmTmXTAl3FyJcDgWCMr6gPhSf8uE/bSTk5JD5AswMEcElMP+6T1zFAgMBAAECgYAk2fsuTukbRi03db4FIWX31Q2IjHQYf/TmgqtduBBG0x/yJY3H6gzGnUnWeAlAAEBqPfDzncGQt94u32ek+ANmN161r22eBqoihHJQsCD3n3uFw8fdCRzpP9fiJVUFf3Yf/Di2G6cHKJ1Bs8H2GtmajeUUgjNNvJdQXLsTU2DBoQJBAPV9Luzcb62BO9GsL/C6nrxOEPnfTOvpQpBDjb4JnnS8G4CRoEERB8y0p/npD7wrhwG1aEpOj/6XUUz8yAqrA50CQQCZ139/lX0W6TGxZF5RQu9PlKW5/K74Ysd6tvuom93bwLG4zpCgfIoH3mSkWtKENvob7CV07T/irYppa/bIpRlJAkARnsqfdbMOYRhKFHHcdYivO2s8hCqhRDzi3fZujYIyHs5ajBlUkkRdDRqBdZkLiJRIKx0xODJds77CJ+Kz4VKBAkAUf14Bhc1w7Aku9YyLjzuLgubB7STy+1ZQx2iognwA95+2W+9xMqbBfaQzMdayvxB7/+7NsX69mRnEChqLiVPhAkEA6W9YOoZQlL6yCYE4GE3W38g0m7lq68XuVFgCpULEfR3s5bsPcqxC4xM29Ry80cEv6fAE+jht7JUq0ar/tRqfNA==";
try {
value = RSAcheck.decryptDatafd(queryString, privateKey);
}catch (Exception e){
log.error("解密失败,按照未加密参数使用");
value = "";
}
log.info("----请求 value: "+value);
if(value!=null&&!"".equals(value)) {
if("GET".equals(method)) {
String[] params = value.split("&");
for (String param : params) {
String[] pvalue = param.split("=");
this.addParameter(pvalue[0], pvalue[1]);
//this.addParameterToBody(pvalue[0], pvalue[1]);
}
}else if("POST".equals(method)) {
this.body = getData(value).getBytes();
}
}else{
String json = queryString;
if (!StringUtils.isEmpty(json)) {
// body 赋值
this.body = getData(json).getBytes();
}
// 请求参数赋值
this.params.putAll(request.getParameterMap());
}
}
}catch (Exception e){
log.error("异常",e);
}
}
/**
* 重载一个构造方法-- 扩展参数
*
* @param request
* @param extendParams
*/
public ParameterRequestWrapper(HttpServletRequest request, Map<String, Object> extendParams,String privateKey) {
this(request,privateKey);
//这里将扩展参数写入参数表
addAllParameters(extendParams);
}
/**
* 增加多个参数
*
* @param otherParams
*/
public void addAllParameters(Map<String, Object> otherParams) {
for (Map.Entry<String, Object> entry : otherParams.entrySet()) {
addParameter(entry.getKey(), entry.getValue());
}
}
/**
* 增加参数
*/
public void addParameter(String name, Object value) {
if (value != null) {
if (value instanceof String[]) {
params.put(name, (String[]) value);
} else if (value instanceof String) {
params.put(name, new String[]{(String) value});
} else {
params.put(name, new String[]{String.valueOf(value)});
}
}
}
/**
* 增加body 参数
*
* @param name
* @param value
*/
public void addParameterToBody(String name, Object value) {
byte[] json = this.body;
if (null == json) {
json = new byte[0];
}
String jsonStr = new String(json);
try {
Map<String, Object> mapData = new HashMap<>();
if(jsonStr!=null&&!"".equals(jsonStr)){
mapData = JSONObject.parseObject(jsonStr, Map.class);
}
mapData.put(name, value);
this.body = JSONObject.toJSONString(mapData).getBytes();
} catch (Exception ex) {
log.error("body体赋值错误",ex);
// 转换异常
}
}
/**
* body中参数解密
*
* @param json
* @return
*/
private String getData(String json) {
//加密如果传过来的是加密数据先解密未加密直接返回原json
//不加密
return json;
}
/**
* 获取body 参数
*
* @param request
* @return
*/
public static String getPostData(HttpServletRequest request) {
StringBuilder data = new StringBuilder();
String line;
BufferedReader reader;
try {
reader = request.getReader();
while (null != (line = reader.readLine())) {
data.append(line);
}
} catch (IOException e) {
return null;
}
return data.toString();
}
@Override
public String getParameter(String name) {//重写getParameter代表参数从当前类中的map获取
String[] values = params.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}
@Override
public String[] getParameterValues(String name) {//同上
return params.get(name);
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
/**
* 在使用@RequestBody注解的时候其实框架是调用了getInputStream()方法,所以我们要重写这个方法
*
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream() throws IOException {
if (body == null) {
body = new byte[0];
}
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
public String getBody() {
return Base64.getEncoder().encodeToString(this.body);
}
}

View File

@ -0,0 +1,456 @@
package com.chinaunicom.mall.ebtp.cloud.security.starter.common;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.*;
public class RSAcheck {
public static final String KEY_ALGORITHM = "RSA";
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
private static final String PUBLIC_KEY = "RSAPublicKey";
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
* 初始化密钥
*
* @return
* @throws Exception
*/
public static Map<String, Object> initKey() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(512);
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// logger.info("------" + publicKey);
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// logger.info("------" + publicKey);
Map<String, Object> keyMap = new HashMap <String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 取得私钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 取得公钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 解密<br>
* 用私钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data, String key)
throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 解密<br>
* 用私钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static String decryptByPrivateKeyString(byte[] data, String key)
throws Exception {
return new String(decryptByPrivateKey(data, key));
}
/**
* 解密<br>
* 用公钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data, String key)
throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 加密<br>
* 用公钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static String encrypt(String data, String key)
throws Exception {
byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
byte[] value = encryptByPublicKey(dataBytes,key);
return encryptBASE64(value);
}
/**
* 加密<br>
* 用公钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String key)
throws Exception {
// 对公钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 加密<br>
* 用私钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String key)
throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 用私钥对信息生成数字签名
*
* @param data
* 加密数据
* @param privateKey
* 私钥
*
* @return
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
// 解密由base64编码的私钥
byte[] keyBytes = decryptBASE64(privateKey);
// 构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取私钥匙对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 用私钥对信息生成数字签名
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return encryptBASE64(signature.sign());
}
/**
* 校验数字签名
*
* @param data
* 加密数据
* @param publicKey
* 公钥
* @param sign
* 数字签名
*
* @return 校验成功返回true 失败返回false
* @throws Exception
*
*/
public static boolean verify(byte[] data, String publicKey, String sign)
throws Exception {
// 解密由base64编码的公钥
byte[] keyBytes = decryptBASE64(publicKey);
// 构造X509EncodedKeySpec对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取公钥匙对象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 验证签名是否正常
return signature.verify(decryptBASE64(sign));
}
public static byte[] decryptBASE64(String key) throws Exception {
return Base64.getDecoder().decode(key);
}
private static String encryptBASE64(byte[] key) throws Exception {
return Base64.getEncoder().encodeToString(key);
}
public static void main(String[] args) {
Map<String, Object> keyMap;
try {
//keyMap = initKey();
//Map map = initKey();
//System.out.println(map);
//System.out.println(keyMap);
//取得公钥和么私钥
//keyMap = initKey();
String publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJOzdznkEvViWv7+XV/7PfwwiqSfJDo0dWa4dV/kxffLnahmxgVposlZNkqhjwOEPZFAlsOOgqHIxNOO4MeQBa0CAwEAAQ==";
//getPublicKey(keyMap);
// //
System.out.println("字符类型公钥:" + publicKey);
String privateKey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAk7N3OeQS9WJa/v5dX/s9/DCKpJ8kOjR1Zrh1X+TF98udqGbGBWmiyVk2SqGPA4Q9kUCWw46CocjE047gx5AFrQIDAQABAkAIHG/stvCvlxImNLPOBI8X3VaPycmEhML5vCF9/aM9g1SuFa298Q5W8FqAmm8SE5lRpw2yyToWtLbufJtAa7wFAiEAxViJBkLU4wfPCwiPiAn17owXbocC9rj3fAzEH9DYDdcCIQC/mZp4ujO035Qqw2QQeFWpDc/vITx1OTWaxq6/LvvwGwIgXTZLSmzItw9aKOD7QotJ4UnES41zxetp4er5u/leA3MCIGcRw2ZEjII1b+hdOdweT75kfsId9/77apm7Xc/c/4yXAiEAnBrCiVXRNN+slO0MYaxynr4eIiPG/EjYBYxXlwBpeOc=";
//getPrivateKey(keyMap);//
System.out.println("字符类型私钥:" + privateKey);
System.out.println("公钥加密——私钥解密---------------");
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String source = "831357ef-3a80-40b3-9563-6451a7a8d605_"+(format.format(new Date()));
// System.out.println("\r加密前文字\r\n" + source);
// byte[] data = source.getBytes();
// byte[] encodedData = encryptByPublicKey(data, publicKey);
//
// System.out.println("加密后文字:\r\n" + encryptBASE64(encodedData));
// byte[] decodedData = decryptByPrivateKey(encodedData, privateKey);
// String target = new String(decodedData);
// System.out.println("解密后文字: \r\n" + target);
System.out.println("\r加密前文字\r\n" + source);
String ciphertext = encryptDatafd(source, publicKey);
System.out.println(ciphertext);
String data = decryptDatafd(ciphertext, privateKey);
System.out.println(data);
String data2 = decryptDatafd("IaDxV6UytgKPh2g/4fh2jvuiKJV7bRrbaSG7jqZ+94oOsCsxvL1wMl09tAF8B2N2Eex4vKtt/LQvouLJXdlBVg==", privateKey);
System.out.println(data2);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* String转私钥PrivateKey
*
* @param key
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = org.apache.commons.codec.binary.Base64.decodeBase64(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
// 最大明文加密长度(单位:字节)
private final static int MAX_ENCRYPT_BLOCK = 245;
// 最大密文解密长度(单位:字节)
private final static int MAX_DECRYPT_BLOCK = 256;
/**
* 分段加密数据
*
* @param data 待加密的数据
* @param publicKeyStr 公钥字符串
* @return 经过Base64编码的加密好的数据
* @throws Exception
*/
public static String encryptDatafd(String data, String publicKeyStr) throws Exception {
// 1.将公钥字符串转换为字节数组
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
// 2.根据公钥字符串生成publicKey
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicKey = factory.generatePublic(spec);
// 3.将待加密数据字符串转换为字节数组
byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
// 4.分段加密
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
ByteArrayOutputStream output = new ByteArrayOutputStream();
int dataLength = dataBytes.length;
int offSet = 0;
byte[] cache;
while (dataLength - offSet > 0) {
if (dataLength - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offSet, dataLength - offSet);
}
output.write(cache, 0, cache.length);
offSet += MAX_ENCRYPT_BLOCK;
}
output.close();
// 5.返回Base64编码后的字符串
return Base64.getEncoder().encodeToString(output.toByteArray());
}
/**
* 用私钥 解密
*
* @param encryptionBase64Str RSA加密后又base64编码后的字符串
* @return 解密结果
* @throws Exception
*/
public static String decrypt(String encryptionBase64Str,String priKey) throws Exception {
//String priKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANJ1Z5PNYU6HTG7nSFcnoPzGJaOQQYqCnQVnsF1GeFZIxdGNx1yweGVyweOljcJijRIWjFWRV23DiLpS2KkHzx72fMRKaMn/NqXuDxqnLquBmNDCutprmJ+v1RVkkd3GHPLiRAizfKoMcQpqK0Ax9hY4oIX7bLi1u/t4dSaNH40PAgMBAAECgYBNMJx1vF1VNRCWmKOSu8kzDOXfMNipGbDHu7kW7PLUCsrrSgn1+A+gfc+ZVC5DPmwpVzXPaIhdjNsII7ytely/fw6BZjoToIk31QZDOAz4CpImzSiwnrVpLiDLZH7fykqUOlXomjc6qVpKfjvOUQHNF46EmCNlb6QX/ZWJwFPPsQJBAPKsuaT14JL98kLUXhuv/yV/FRMqgSoskEQD9JRjWbXuSlekx13f/ODTfBHMwX/hTofjAOtQyPs/bI5JtfrllLcCQQDeA9F3y/315h2rDtraJ9HM37pZ6MppAj2VkO7/uLiZX/Pswz45JUyTu5dkbsM7YgZ1iixfDzw32FBmtULRtOJpAkEAsx5khGrr0PNZ/pPrxnn4VL/hWV01K2DrNxjITUKrs8pn2xsIALVUXMocuLKuXGp74XbfddESF8jvonKrvL36LwJBAM2a8aElDLNugelJ34oLOHOoejcLrHAlQA1EZOH0GxkHUKnigrx/e3SRVPoQzcMv29V8uezq+hSpwoPrt87n2okCQFsULqFWm+COhWTkCuye27ipR6w3F7JSmj96Y2773F2LAb//vlsRftz517AcbHX74G4Icy02OV2AToyUi9lL9lo=";//getPrivateKey(keyMap);
// base64 解码
byte[] base64 = org.apache.commons.codec.binary.Base64.decodeBase64(encryptionBase64Str);
// String 转 私钥decryptByPrivateKey
PrivateKey rsaPrivateKey = getPrivateKey(priKey);
//私钥解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(base64);
return new String(result);
}
/**
* 分段解密数据
*
* @param ciphertext 密文
* @param privateKeyStr 私钥字符串
* @return 解密后的数据
* @throws Exception
*/
public static String decryptDatafd(String ciphertext, String privateKeyStr) throws Exception {
// 1.将私钥字符串转换为字节数组
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
// 2.根据私钥字符串生成privateKey
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateKey = factory.generatePrivate(spec);
// 3.解码Base64字符串转换为字节数组
byte[] dataBytes = Base64.getDecoder().decode(ciphertext);
// 4.分段解密
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
ByteArrayOutputStream output = new ByteArrayOutputStream();
int dataLength = dataBytes.length;
int offSet = 0;
byte[] cache;
while (dataLength - offSet > 0) {
if (dataLength - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offSet, dataLength - offSet);
}
output.write(cache, 0, cache.length);
offSet += MAX_DECRYPT_BLOCK;
}
output.close();
// 返回解密好的原始数据
return output.toString();
}
}

View File

@ -0,0 +1,127 @@
package com.chinaunicom.mall.ebtp.cloud.security.starter.common;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class RsaTest {
// 算法类型
private final static String KEY_ALGORITHM = "RSA";
// 最大明文加密长度(单位:字节)
private final static int MAX_ENCRYPT_BLOCK = 245;
// 最大密文解密长度(单位:字节)
private final static int MAX_DECRYPT_BLOCK = 256;
/**
* 分段加密数据
*
* @param data 待加密的数据
* @param publicKeyStr 公钥字符串
* @return 经过Base64编码的加密好的数据
* @throws Exception
*/
public static String encryptData(String data, String publicKeyStr) throws Exception {
// 1.将公钥字符串转换为字节数组
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
// 2.根据公钥字符串生成publicKey
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicKey = factory.generatePublic(spec);
// 3.将待加密数据字符串转换为字节数组
byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
// 4.分段加密
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
ByteArrayOutputStream output = new ByteArrayOutputStream();
int dataLength = dataBytes.length;
int offSet = 0;
byte[] cache;
while (dataLength - offSet > 0) {
if (dataLength - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offSet, dataLength - offSet);
}
output.write(cache, 0, cache.length);
offSet += MAX_ENCRYPT_BLOCK;
}
output.close();
// 5.返回Base64编码后的字符串
return Base64.getEncoder().encodeToString(output.toByteArray());
}
/**
* 分段解密数据
*
* @param ciphertext 密文
* @param privateKeyStr 私钥字符串
* @return 解密后的数据
* @throws Exception
*/
public static String decryptData(String ciphertext, String privateKeyStr) throws Exception {
// 1.将私钥字符串转换为字节数组
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
// 2.根据私钥字符串生成privateKey
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateKey = factory.generatePrivate(spec);
// 3.解码Base64字符串转换为字节数组
byte[] dataBytes = Base64.getDecoder().decode(ciphertext);
// 4.分段解密
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
ByteArrayOutputStream output = new ByteArrayOutputStream();
int dataLength = dataBytes.length;
int offSet = 0;
byte[] cache;
while (dataLength - offSet > 0) {
if (dataLength - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offSet, dataLength - offSet);
}
output.write(cache, 0, cache.length);
offSet += MAX_DECRYPT_BLOCK;
}
output.close();
// 返回解密好的原始数据
return output.toString();
}
public static void main(String[] args) throws Exception {
String publicKeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArF9CK/qMzej1vifFCINwp+7V4otEtVpCP0SIflQMvXjFqDyMuWZS4epwbZ2D6Ko5n3GPtHXs9vcVvw2kaGrmuKDbbASQyVlVCY1y91AsTJCTaF6DRa7cY/rYwvqHOc3XZZT86mes0MZmulGDt0V/0p7LdglZpBJrAXg9ANvIcBW8eQERleQPhszYPzQP3YUD6ogI3u6QRhR8uVSWqVrs5naVuNROTuZk/6ZG6rpXrzjniYLYT8TfT41fcL5JClDM51I96s9fJw3mfHFe9qlkWj9pdB76G44+mR+UHAvP96RQ35c6HmsLOu6I8PV0BM5+OzU0l5qVltmgs3Yr9RM5EwIDAQAB";
String privateKeyStr = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCsX0Ir+ozN6PW+J8UIg3Cn7tXii0S1WkI/RIh+VAy9eMWoPIy5ZlLh6nBtnYPoqjmfcY+0dez29xW/DaRoaua4oNtsBJDJWVUJjXL3UCxMkJNoXoNFrtxj+tjC+oc5zddllPzqZ6zQxma6UYO3RX/Snst2CVmkEmsBeD0A28hwFbx5ARGV5A+GzNg/NA/dhQPqiAje7pBGFHy5VJapWuzmdpW41E5O5mT/pkbqulevOOeJgthPxN9PjV9wvkkKUMznUj3qz18nDeZ8cV72qWRaP2l0Hvobjj6ZH5QcC8/3pFDflzoeaws67ojw9XQEzn47NTSXmpWW2aCzdiv1EzkTAgMBAAECggEAdWAsfCwRw4lWBZWpOwHeLcyaArkZIXED2Xc+ht+PCVp7JfONVBZUbBgrVMlE8KMxt9wpohYHNajNOxr8EEpzL9gBco2tVh6ppGaYmcYTVFPCvPhW5ZWL590By8uzV25OtZJ9otTUPhpMC6XEToFZ6D9PhuIZE3ujOA37ZGFFHOTfOaumAO/JOAywib+PzyqVOeqbLn9fxeMwiV7FQv4tfykmRjdidyXF51T1GYhKS4U15Rj9UEx5PUJlc36SWY/9bWOGSoEZd+JhzlXP88kK2kttiWj/exX8FYWFbeaRhPkK4YQ6+i3MbNxqz0NRJaEKQmCFtw1fSRC6NzlvuYZ7AQKBgQDybNJZf0M0x9NltOIzycu6MyOTIeO3tCUapQlxa5e7KzZS7j320f+juTNw4O3pt5Cklsb5CwGZPn/09RXC67ULRCtPHPHz69n19dNa1tVofu4jUT/UYTfe54xnGBtx1XMBEhWVJkucd6aaUr5yiO50uavPRHZmoUUA92aM0wr4gQKBgQC2BjkamkTxwvNFior8VDAHq376mXewBf6ybSS5lMamiOvqYpCONeCPMJOK84QYFSJI3c1iFKcKpm5rt41kNfE6uEkPjC4zFUZAhafdKi03V3VG3ZzSxFytWzt4wztf/TNq96JZynZHY837qh4D+UuouWNOKdmXMY+IvM2Sk3sHkwKBgQC0WAQ8FBJ5B1baSLAmeq6WPEjwwbtYBCm+Ipxdxf7AfKsTEq0CGsMklzgPdyVGQwrVhl1LE8cCq54hKtofgZ3TXckiN5Q/M2uYMGIlJ8Dm1dZua5kic5hOuM6YOzTfgDznxP5NUInbQp+sGnYXWoqaRy3rKTEztDFTQLkHdlCpAQKBgQCxUFSWLotUuuTB7FjBvrze69eRBKiL5vsaEqoAwgXVOnId65AHiEJNGjPP2rHlx8iTFMW6coXaIRBVjAOHB+kKm3RIWfSzPFkoB0rjbe+IBoEu3DilNDVXhhTj6cLQGdXZsIsNTuVzW6zPKAN/OXzTSmyLOsdEujmpKMpUq6fgUwKBgGHOzITAmMZXn3D9Yh4foPy2kNc9ME/Q2z0A5AKdY4HtZ1hmsmsGjUTPbtGXIJRxYeQHwoDI1xQKbvRJXaG33ulNnvuMl0XSr4XA7uYoAgSL1I+3xrTxTShAsDb42uE5KCsd969cyNfeNdwxF7S8KH0yKcUy5BqOdX4pUlrEQHnI";
String ciphertext = encryptData("{\"maxAmount\":{\"amount\":1,\"projectId\":\"1744965355372617728\"},\"roomType\":\"2\",\"voList\":[{\"annoStructuredType\":\"1\",\"docEndTime\":null,\"docStartTime\":null,\"expenses1Amount\":\"0\",\"expenses1Type\":\"0\",\"expenses4Amount\":null,\"expenses4Type\":\"\",\"expenses5Amount\":\"0\",\"expenses5Type\":null,\"key\":0,\"orderState\":null,\"payment4Method\":\"\",\"projectId\":\"1744965355372617728\",\"sectionId\":\"1744965355389394944\",\"sectionName\":\"结构化202401-1\",\"sendOut\":0},{\"annoStructuredType\":\"1\",\"docEndTime\":null,\"docStartTime\":null,\"expenses1Amount\":\"0\",\"expenses1Type\":\"0\",\"expenses4Amount\":null,\"expenses4Type\":\"\",\"expenses5Amount\":\"0\",\"expenses5Type\":null,\"key\":1,\"orderState\":null,\"payment4Method\":\"\",\"projectId\":\"1744965355372617728\",\"sectionId\":\"1744965355393589251\",\"sectionName\":\"结构化202401-2\",\"sendOut\":0}]}", publicKeyStr);
System.out.println(ciphertext);
String data = decryptData(ciphertext, privateKeyStr);
System.out.println(data);
}
}

View File

@ -3,19 +3,26 @@ package com.chinaunicom.mall.ebtp.cloud.security.starter.filter;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants;
import com.chinaunicom.mall.ebtp.cloud.security.starter.common.RSAcheck;
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.AuthAllows;
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.RoleCodeAuthority;
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.SecurityUser;
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.service.UserInfoService;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseCacheUser;
import com.chinaunicom.mall.ebtp.common.exception.common.CommonExceptionEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.remoting.RemoteTimeoutException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
@ -25,6 +32,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -37,14 +45,30 @@ import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.
* @author Ajaxfan
*/
@Slf4j
@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private UserInfoService client;
//@Value("${http.rsa.privateKey}")
private String privateKey="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCIbZigdtFhreIKKBesIrgPhZoRgbMALpTjnNtAibPjmJJMSuWDnHgvSLpCaqNuCEm2GG5dRcZHTc2HWqGz00AJBxmMvrY8H2OqSAF0DuHGlMFZ4k2rpwY1VK9EJbN1/dTm9ZHxEvCRrUgZAQ1In3pUwflNgriou0/2MMoCL9i22TrAd/x835MCA0H0SxSGr02GhZRVmQMYo7axprr4/7RBUpynwh2ERKyZ6kzPF2qk4NW6lWXQSitOytVHagfxDfIEGjti1t4cnbD8n1DfjmBBpaUrJ2x9JX3Vxp6Gc0OCuqKJSxP73roibop1OXlXFJNn3Ansa0tiEkWuyPIqDAcnAgMBAAECggEAJeFwcJWtO5cBXVqWgBg/zSeGiPffUNyeQLjr8/aIOVjCvmZJZgrLIC3sccaUTFgGx4XvFvzpuiCzQbL7lSfB7v/Gq1rE1NrOXJiTtrrvG6lwKln4wQGmaqZx59UkCE4LkHl9JVfh7kET9MVi/9gwKlqVs1zpkwg3gp83Z/YLEXHFwlgMadDe7vxf/gTTdgH2mPYxI304hUj/lKlomFLiNx1Tn1KGphdklYa+Vx8fjfzmxp+aoxbLrLqnV90udDCQPHy7WzjW2+cYR8rbZmzR/zIbJxz1iIvG0GDVgJti9aJi3qujCAJ84fhG5yHpImIP6VjyHLwv61duPD3zla0bKQKBgQDEa3H2STgfwecK5T4gY72tNf1ZAtv7QajAkRcVoYEuUVSMtSvGZA3XLOjZKF1B8AOjdnxrIs2xh2ig+36EfpMTEwzkB/DBEIbnzCCdCedj+THysUImpdiHrhXpYO6GzvZMUgBtQvPLx2H3hosz0VS0/RiUYCMhIC7gWkp2lSLF6wKBgQCxz6GNW33MMSMjD/CAOwI333f0DtNtWWK+rMeQRXO2EKMg+aIk3Yez3C62EcQYgysm4J2Y0r84BDXKL795sVKWZBMY67qSMntfD2PxI9rHYttKd2sCttrZUB0Btr8j+hp0nd7EGhDVHFvWFqMgMfv+DQAoP1ah0Oa1Mzvto2RItQKBgCc1M2hwMS3VrOL147LfdgtPTaUo9vRupNrbm3oL5Rdz0KbNu1E8w66CHnDKp+LzoCZPDoLsTZb0aqRHz3dvNLiIAvi5xQsk22kFzDTMt02zfo7tZ0EDtfdPfrw5RyPNyEhvzfoBdVzmDd41EzBixr/iDbgAgMKqA/Fw1JBbMLfFAoGBAIFaBrCK6kztQh5zrgXa55Y131GQp4ZZDFih4Nu3aqH8IHAQqkAfWGUjvGd/LSSX54B0zrEqPylFBsx7R9QDh40YaDws4KESUGWrEI2QA8wgwl692P80fqiweymQBCTsAOrtHe2S+MPPyY9JEIqPUj5SvtaInUFCc1NGXkZWItIxAoGACKFRZOwxSUgGiK3YkQILO7Jy7jS0EMG8Bo0tuxjgBRCB2QgUe5TzFpkjSOjgqID5NRaFmthsfpOWmLgANne59tCozjmbGhLKSb+py/j3r5w2uWnDDVrZ0hcPqIFR+8y6c1sus5VnaKfDd/Sm4Tc4DFPNld+CKnJPtMxZUE51m78=";
@Value("${check.tokentime.timeLimit}")
private String kswTimeLimit;// = "20";
@Value("${check.tokentime.onof}")
private String onof;// = "0";
@Value("${check.tokentime.checkprivateKey}")
private String checkprivateKey;//="MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAk7N3OeQS9WJa/v5dX/s9/DCKpJ8kOjR1Zrh1X+TF98udqGbGBWmiyVk2SqGPA4Q9kUCWw46CocjE047gx5AFrQIDAQABAkAIHG/stvCvlxImNLPOBI8X3VaPycmEhML5vCF9/aM9g1SuFa298Q5W8FqAmm8SE5lRpw2yyToWtLbufJtAa7wFAiEAxViJBkLU4wfPCwiPiAn17owXbocC9rj3fAzEH9DYDdcCIQC/mZp4ujO035Qqw2QQeFWpDc/vITx1OTWaxq6/LvvwGwIgXTZLSmzItw9aKOD7QotJ4UnES41zxetp4er5u/leA3MCIGcRw2ZEjII1b+hdOdweT75kfsId9/77apm7Xc/c/4yXAiEAnBrCiVXRNN+slO0MYaxynr4eIiPG/EjYBYxXlwBpeOc=";
@Value("${check.tokentime.checkpublicKey}")
private String checkpublicKey;//"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJOzdznkEvViWv7+XV/7PfwwiqSfJDo0dWa4dV/kxffLnahmxgVposlZNkqhjwOEPZFAlsOOgqHIxNOO4MeQBa0CAwEAAQ==";
@Autowired
private AuthAllows allows;
//private String checkprivateKey="MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAk7N3OeQS9WJa/v5dX/s9/DCKpJ8kOjR1Zrh1X+TF98udqGbGBWmiyVk2SqGPA4Q9kUCWw46CocjE047gx5AFrQIDAQABAkAIHG/stvCvlxImNLPOBI8X3VaPycmEhML5vCF9/aM9g1SuFa298Q5W8FqAmm8SE5lRpw2yyToWtLbufJtAa7wFAiEAxViJBkLU4wfPCwiPiAn17owXbocC9rj3fAzEH9DYDdcCIQC/mZp4ujO035Qqw2QQeFWpDc/vITx1OTWaxq6/LvvwGwIgXTZLSmzItw9aKOD7QotJ4UnES41zxetp4er5u/leA3MCIGcRw2ZEjII1b+hdOdweT75kfsId9/77apm7Xc/c/4yXAiEAnBrCiVXRNN+slO0MYaxynr4eIiPG/EjYBYxXlwBpeOc=";
@Autowired(required = false)
@Qualifier("userinfoRedisTemplate")
private RedisTemplate<String, Object> redisTemplate;
/**
* @param request
* @param response
@ -55,11 +79,27 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException {
//解密 恢复请求参数
//ParameterRequestWrapper requestWrapper = new ParameterRequestWrapper((HttpServletRequest) request,privateKey);
String api = request.getRequestURI();
String method = request.getMethod();
if (!StringUtils.contains(api, ACTUATOR_PROMETHEUS)) {
log.info("--------" + method + " - " + api + "?" + Optional.ofNullable(request.getQueryString()).orElse(""));
}
String check_header = request.getHeader(HEADER_CHECK_TOKEN);
log.info("HEADER_CHECK_TOKEN:"+HEADER_CHECK_TOKEN);
log.info("check_header:"+check_header);
String isFeginKey = request.getHeader("isFegin");
log.info("isFeginKey: " + isFeginKey);
String isFegin = null;
if(isFeginKey!=null&&!"".equals(isFeginKey)) {
try {
isFegin = RSAcheck.decrypt(isFeginKey, checkprivateKey);
} catch (Exception e) {
log.error("isFegin 解密异常", e);
}
}
// 清空上下文中的缓存信息, 防止二次请求时数据异常 (如此, 每次有新的请求进入都会进行token的验证)
SecurityContextHolder.getContext().setAuthentication(null);
@ -77,11 +117,13 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
final String header = request.getHeader(AUTHORIZATION_HEADER);
final String currentRoleCode = request.getHeader(CURRENT_ROLE_CODE);
log.debug("header:{},currentRoleCode:{}", header, currentRoleCode);
Boolean tokenCheckB = false;
try {
// 检查请求头是否包含 Bearer 前缀
if (StringUtils.startsWith(header, Constants.TOKEN_PREFIX)) {
setAuthentication(currentRoleCode, RegExUtils.replaceAll(header, Constants.TOKEN_PREFIX, ""), isWhite);// 移除header的前缀提取出token字串
tokenCheckB = true;
}
// 检查cookie
else {
@ -102,9 +144,110 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
ExceptionUtil.stacktraceToString(e);
log.error(e.getMessage());
}
//校验token 时间戳
log.info("校验token时间戳");
if(tokenCheckB) {
if (!api.contains(ACTUATOR_HEALTH) && !api.contains(ACTUATOR_PROMETHEUS)
&& (isFegin == null || !"isFegin".equals(isFegin))) {
BaseCacheUser buser = new BaseCacheUser();
BeanUtils.copyProperties(SecurityContextHolder.getContext().getAuthentication().getPrincipal(), buser);
log.info("获取用户信息:" + buser);
if (buser != null && buser.getUserId() != null && !"".equals(buser.getUserId())) {
if (!checkTokenTime(request, response, filterChain)) {
request.getSession().setAttribute("code", "90501");
CommonExceptionEnum.FRAME_EXCEPTION_COMMON_DATA_OTHER_ERROR.customValidName("无效请求", true);
}
}
}
}
// 过滤链调用
filterChain.doFilter(request, response);
}
/**
* 校验请求唯一性
* @param request
*/
public Boolean checkTokenTime(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain){
Boolean b = true;
String check_header = request.getHeader(HEADER_CHECK_TOKEN);
log.info("request check_header:"+check_header);
if("1".equals(onof)){
return true;
}
// Optional<Cookie> optionalCookie = Optional.ofNullable(request.getCookies())
// .flatMap(cookies ->
// Stream.of(cookies)
// .filter(item -> StringUtils.equals(item.getName(), COOKIE_TOKEN_CODE))
// .findFirst());
if (check_header!=null&&!"".equals(check_header)) {
String cookieKey = check_header;//optionalCookie.get().getValue();
log.info("cookieKey:"+cookieKey);
Object o = redisTemplate.opsForValue().get(HEADER_CHECK_TOKEN+":"+cookieKey);
if (o != null) {
String num = String.valueOf(o);
log.info(HEADER_CHECK_TOKEN+":"+cookieKey+"= "+num);
if("2".equals(num)){
log.error("请求连接已使用过");
b = false;
}else{
redisTemplate.opsForValue().set(HEADER_CHECK_TOKEN+":"+cookieKey, 2, 20, TimeUnit.SECONDS);
}
//request.getSession().setAttribute("code", "90501");
//throw new RemoteTimeoutException(REMOTE_ACCESS_CHECK);//REMOTE_ACCESS_CHECK
//throw new BusinessException(CommonExceptionEnum.LOGIN_CHECK_TOKEN_EXPIRATION, "无效请求 h");
}else{
redisTemplate.opsForValue().set(HEADER_CHECK_TOKEN+":"+cookieKey, 1, 20, TimeUnit.SECONDS);
}
String header = request.getHeader(AUTHORIZATION_HEADER);//请求头token
header = RegExUtils.replaceAll(header, Constants.TOKEN_PREFIX, "");
String cookieValue = "";
try {
cookieValue = RSAcheck.decrypt(cookieKey, checkprivateKey);
}catch (Exception e){
b = false;
//request.getSession().setAttribute("code", "90501");
//throw new RemoteTimeoutException(REMOTE_ACCESS_CHECK);//REMOTE_ACCESS_CHECK
}
log.info("header :"+header);
log.info("cookieValue :"+cookieValue);
String[] checkValues = String.valueOf(cookieValue).split("_");//0 token 1 token 时间
if (!header.equals(checkValues[0])) {
log.error("请求连接token不一致");
b = false;
//request.getSession().setAttribute("code", "90501");
//throw new RemoteTimeoutException(REMOTE_ACCESS_CHECK);//REMOTE_ACCESS_CHECK
//throw new BusinessException(CommonExceptionEnum.LOGIN_CHECK_TOKEN_EXPIRATION, "无效请求 token");
}
//SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
long newDateLong = System.currentTimeMillis();
long inDateLong = Long.valueOf(checkValues[1]).longValue();
log.info("newDateLong:"+newDateLong);
log.info("inDateLong:"+inDateLong);
log.info("kswTimeLimit:"+kswTimeLimit);
log.info("newDateLong - inDateLong :"+(newDateLong - inDateLong));
log.info("newDateLong - inDateLong 结果 :"+((newDateLong - inDateLong) > Long.valueOf(kswTimeLimit).longValue()));
if ((newDateLong - inDateLong) > Long.valueOf(kswTimeLimit).longValue()) {//
log.error("请求已超时");
//request.getSession().setAttribute("code", "90501");
b = false;
//throw new RemoteTimeoutException(REMOTE_ACCESS_CHECK);//REMOTE_ACCESS_CHECK
//throw new BusinessException(CommonExceptionEnum.LOGIN_CHECK_TOKEN_EXPIRATION, "无效请求time out");
}
} else {
log.error("请求未授权");
//request.getSession().setAttribute("code", "90501");
b = false;
//throw new RemoteTimeoutException(REMOTE_ACCESS_CHECK);//REMOTE_ACCESS_CHECK
//throw new BusinessException(CommonExceptionEnum.LOGIN_CHECK_TOKEN_EXPIRATION, "无效请求!");
}
return b;
}
/**
* 白名单验证
*

View File

@ -2,6 +2,7 @@ package com.chinaunicom.mall.ebtp.common.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chinaunicom.mall.ebtp.cloud.security.starter.common.RSAcheck;
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.AuthAllows;
import feign.RequestInterceptor;
import feign.RequestTemplate;
@ -12,8 +13,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRange;
import org.springframework.http.HttpRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@ -45,6 +44,10 @@ public class FeignConfig implements RequestInterceptor {
List<String> tokenWhiteList;
@Autowired
private AuthAllows allows;
@Value("${check.tokentime.checkprivateKey}")
private String checkprivateKey;//="MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAk7N3OeQS9WJa/v5dX/s9/DCKpJ8kOjR1Zrh1X+TF98udqGbGBWmiyVk2SqGPA4Q9kUCWw46CocjE047gx5AFrQIDAQABAkAIHG/stvCvlxImNLPOBI8X3VaPycmEhML5vCF9/aM9g1SuFa298Q5W8FqAmm8SE5lRpw2yyToWtLbufJtAa7wFAiEAxViJBkLU4wfPCwiPiAn17owXbocC9rj3fAzEH9DYDdcCIQC/mZp4ujO035Qqw2QQeFWpDc/vITx1OTWaxq6/LvvwGwIgXTZLSmzItw9aKOD7QotJ4UnES41zxetp4er5u/leA3MCIGcRw2ZEjII1b+hdOdweT75kfsId9/77apm7Xc/c/4yXAiEAnBrCiVXRNN+slO0MYaxynr4eIiPG/EjYBYxXlwBpeOc=";
@Value("${check.tokentime.checkpublicKey}")
private String checkpublicKey;//"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJOzdznkEvViWv7+XV/7PfwwiqSfJDo0dWa4dV/kxffLnahmxgVposlZNkqhjwOEPZFAlsOOgqHIxNOO4MeQBa0CAwEAAQ==";
/**
* @param template
@ -54,6 +57,15 @@ public class FeignConfig implements RequestInterceptor {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
log.info("--------feign url- " + template.url());
String method = template.method();
try {
//long newDateLong = System.currentTimeMillis();
String key = RSAcheck.encrypt("isFegin", checkpublicKey);
template.header("isFegin", key);
}catch (Exception e){
log.error("fegin加密异常");
}
if (Objects.nonNull(attributes)) {
if (isNonExistsWhiteList(template.url())) {
injectToken(template, attributes);
@ -70,6 +82,7 @@ public class FeignConfig implements RequestInterceptor {
log.info("attributes is null=======accessToken===" + accessToken);
template.header(HttpHeaders.AUTHORIZATION, String.format("%s%s", TOKEN_PREFIX, accessToken));
}
}

View File

@ -49,7 +49,11 @@ public enum CommonExceptionEnum implements BusinessExceptionAssert {
/**
* 登陆已超期
*/
LOGIN_EXPIRATION(90401, "登陆已超期");
LOGIN_EXPIRATION(90401, "登陆已超期"),
/**
* 无效请求
*/
LOGIN_CHECK_TOKEN_EXPIRATION(90501, "无效请求");
/**
* 返回码

View File

@ -150,3 +150,8 @@ management:
cors:
allowed-origins: "*"
allowed-methods: "*"
http:
rsa:
publicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNR+qWwx1SFELNYCk3vqqQ9wAgr7il6/yRPnwk/Vq+7UAlUyOrlTb9ZAKAxJE7OjoqQHpPJkXYypqlNkkpYrRHKc3lTeSXFL1AOU6idtidTC1W7STwNNYJ1RtFA7qqVd4C/+pbU0GHZ2OMsMbFr+b40pienLBg0FGGGCoRVbOSxwIDAQAB
privateKey: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM1H6pbDHVIUQs1gKTe+qpD3ACCvuKXr/JE+fCT9Wr7tQCVTI6uVNv1kAoDEkTs6OipAek8mRdjKmqU2SSlitEcpzeVN5JcUvUA5TqJ22J1MLVbtJPA01gnVG0UDuqpV3gL/6ltTQYdnY4ywxsWv5vjSmJ6csGDQUYYYKhFVs5LHAgMBAAECgYBJsk/d4B5eoTd6U9N4V9MUSBibo3o+1wHNgwk+nlY9xR8KR1a++srLHWRopikdgkHveUZvs+XPdq0eMucBHJZrcVT9ZT4ehPmCyRZzILjKqZugP5MpTj1CtM5SfQtxsfuJmM5LYvVX2lmYQw2k+MyWNfyrVfH6HVvu19l1sBqpAQJBAOW2LlqTACRPD3+IOFrHlRQvuUrLq38eRFZCRte2UEq0fMv8VKlgwZdMynD40LwAeO0Cz9huQkNFx4WGxOXthnECQQDkxf43WY6MltfTATYQy4h/TKHznKG+9dMNVFf3SkNECGh5IcW21v44s5X6zOl6zbPVtiySq/c2t9/IbbSc2/i3AkAa3q6ZZayUkrLrZhHBfKsRi2uPNje/TNkNhf8naGoH8wjOC5wTm//JJPBhOpmgBCYhAz0wweT6XYUzN0p84sXhAkEAh7ak7nTkSaaadgQ77I6xdMMjN/9tPHlcMIYegQa/DLboMyPDxImZ2k0+5b91qnIpAtjFbGUzjHRb/uyFvqAH1QJBAJsS6/GhMoCDyPdGQAMA+KylB1s6o8sowLx92q6oBs03idtvFxAocIej1m1UuCW+EpT+ZoFwOn+sdCm5VKfVoLQ=

View File

@ -6,13 +6,13 @@
<parent>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-parent</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<relativePath>../mall-ebtp-cloud-parent</relativePath>
</parent>
<groupId>com.chinaunicom.mall.ebtp</groupId>
<artifactId>uboot-core</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
<name>uboot-core</name>
<dependencies>
@ -20,7 +20,7 @@
<dependency>
<groupId>com.chinaunicom.mall.ebtp</groupId>
<artifactId>uboot-common</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.0-SNAPSHOT</version>
</dependency>
<dependency>