提交 226bd46b 编写于 作者: zlt2000's avatar zlt2000

feat:支持授权参数加密

上级 1801d44a
......@@ -7,6 +7,11 @@ import lombok.Setter;
* 认证配置
*
* @author zlt
* @version 1.0
* @date 2019/1/19
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......@@ -47,4 +52,10 @@ public class AuthProperties {
* false: 就算使用同一账号登录时都会新建一个token
*/
private Boolean isShareToken = true;
/**
* 参数加密(rsa),对应的私钥(用于解密)
* 默认私钥对应的公钥为:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6u4sP969hZP7BUEeAXJlq5wEmZ2CIZU4+5JADY8Ium55qGaE5qXEwMaV+M2HFWU4PZbHfH+RGEIMwjkARRok93krFnJuuwTjLwgyUSsKm5M7v3Ek8zdqs474v1qOxqE6BmHz9QJfgnAtFYxwEyVRoQ12+IAhpOzDU3rz02VR05kGCrgGU6szxDtp6cQ+u9ACGPy/uKdIQ6H7aM/oxMyPlwK9H38ni6Lxai7q56qp6F1p7drxh8CWJZ3j0NicB5ZPnOMtrGL5lfnifHBjB+CDJXv8kffY0zwL3J+LrnyFbpKeNeMJZpykoYW85Pdz+8WnE9KGMM3EeOeD/QX/OfMdFQIDAQAB
*/
private String decryptParamPrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDq7iw/3r2Fk/sFQR4BcmWrnASZnYIhlTj7kkANjwi6bnmoZoTmpcTAxpX4zYcVZTg9lsd8f5EYQgzCOQBFGiT3eSsWcm67BOMvCDJRKwqbkzu/cSTzN2qzjvi/Wo7GoToGYfP1Al+CcC0VjHATJVGhDXb4gCGk7MNTevPTZVHTmQYKuAZTqzPEO2npxD670AIY/L+4p0hDoftoz+jEzI+XAr0ffyeLovFqLurnqqnoXWnt2vGHwJYlnePQ2JwHlk+c4y2sYvmV+eJ8cGMH4IMle/yR99jTPAvcn4uufIVukp414wlmnKShhbzk93P7xacT0oYwzcR454P9Bf858x0VAgMBAAECggEBAJxK94VGWi+T01wbhirQQHN6yFSqRPiyncY/9f0PO29MMAOosKIBhnP5qaxsj4HcZR4UQYLCG3VX+8T6xwMx8YXyRogYeTJSfhG8Ej2NtPDrcsRaMYrdQ09RvosPZA0hFclJQVOu0HumxVegpq8WFMhgfNW16KwgF5JiKfRpY5aw4NDWZFmdNExdymrWPheI8pWBq/U+l8oqrekhbiEKXM2UXmLlKTS9Nk46LRYwaaiDW8JEFuPdx0cnakb+ecCXGd/8Cc8Hxn/mLyvqS1cWHT3J+lXRkfcnNnrJTR9qhf9l077XBMJqVckFEpK4kKbXHZd957ISAxq48Tm+xMX9KAECgYEA995szPToU0BxTTtOD4Z4c5JvbURQEcDQl/dB+qCQnu/orW5ZWv4++lHq2SZPjzbt7M8OaoRN8A5zYcNrYe4kBhLOLqHdaS1yUGIIjAejEAJplR5GqI3T5qzaLjpyiUZpO0mOcwAazCevnSXH6uO5jP0sjwxwaXz4OsTcpHIXHqECgYEA8qMXhh+G88+vTELL/2dHhtTIf7IAJLQ37c1Xrm6uwOHPfiDr256Lc4EzF8QAQqlHoYm1jRK7xDfFymY/SJKJVhYehWlNilnMuDuDOqseC/Zn2KgjMSjLLVkbp25DcpAu6SSiWlBvemrV3jivX/MU0BFp8HjbrlUcl12lRtYgrfUCgYB+iN2iA6RWW597fbrr0gnLdgXMEgOODJBwA5l7CFzLxk1Ru/OBsCkWQJtTH2ueALyVF16UodXnpnjgf5Jh++AH+bGnvJn7B2hEAMe8NGnZ0mFz7nDDuyNhrvvyfYPa8EboLTS7IGKNtfTAlHjqQDaI8vW8UO1R7KoL1lOM33FOAQKBgQDt/Z6jReU+3CUbbiFeANWdoLSQ2+1cExEQxWsNgy8Rreux0WTG4/nwb3fIBc4jlJrYDZTwLMHTssjkv+muq1zd/ZAuV51g6LfutSEAuLseDLDLSBBMtbCkaFTBo1uw0U/SCsbcQy01K/leoMcUG//8HjiFUGZZ1s3WgloM4xbmyQKBgAipgnoEyzvUfe2OMOc5ARGNSGZG4JGTGCyfnrYvYfffWpAokklHOkZMumeSWJXkx5F+MgJd9fxBK9S57PZ09gWkoeSVg0xcz5QMjh8BswfCdyet/CXQtwIfK0Wf1gWdAxC6vvv3DQ7zXbTlvqMdVOFzCKlocCYkzWMvIsejWXnW";
}
......@@ -10,6 +10,11 @@ import java.util.List;
* 配置需要放权的url白名单
*
* @author zlt
* @version 1.0
* @date 2019/1/19
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......
......@@ -10,7 +10,11 @@ import java.util.List;
* 续签配置
*
* @author zlt
* @version 1.0
* @date 2019/7/9
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......
......@@ -7,7 +7,11 @@ import org.springframework.cloud.context.config.annotation.RefreshScope;
/**
* @author zlt
* @version 1.0
* @date 2019/1/4
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......
......@@ -10,7 +10,11 @@ import java.util.List;
* url权限配置
*
* @author zlt
* @version 1.0
* @date 2019/8/2
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......
package com.central.oauth.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
......
......@@ -3,19 +3,21 @@ package com.central.oauth.filter;
import com.central.common.constant.SecurityConstants;
import com.central.common.context.TenantContextHolder;
import com.central.common.model.Result;
import com.central.oauth.handler.decryptParamHandler.IDecryptParamHandler;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.security.Principal;
import java.util.Map;
......@@ -34,17 +36,23 @@ import java.util.Map;
@Component
@Aspect
public class OauthTokenAspect {
@Resource
private IDecryptParamHandler decryptParamHandler;
@Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
public Object handleControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable {
try {
Object[] args = joinPoint.getArgs();
Principal principal = (Principal) args[0];
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException(
throw new OAuth2Exception(
"There is no client authentication. Try adding an appropriate authentication filter.");
}
String clientId = getClientId(principal);
Map<String, String> parameters = (Map<String, String>) args[1];
//解密参数
decryptParamHandler.decryptParams(parameters);
String grantType = parameters.get(OAuth2Utils.GRANT_TYPE);
if (!parameters.containsKey(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME)) {
parameters.put(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME, SecurityConstants.DEF_ACCOUNT_TYPE);
......@@ -74,7 +82,7 @@ public class OauthTokenAspect {
private String getClientId(Principal principal) {
Authentication client = (Authentication) principal;
if (!client.isAuthenticated()) {
throw new InsufficientAuthenticationException("The client is not authenticated.");
throw new OAuth2Exception("The client is not authenticated.");
}
String clientId = client.getName();
if (client instanceof OAuth2Authentication) {
......
package com.central.oauth.handler.decryptParamHandler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import java.util.Map;
/**
* 解密参数的处理接口
*
* @author zlt
* @version 1.0
* @date 2022/12/29
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
public interface IDecryptParamHandler {
String SEPARATOR = ";";
/**
* 需要解密的参数名,多个以 ; 隔离
* 例如:decrypt_param=username;password
*/
String PARAM_KEY_DECRYPT_PARAM = "decrypt_param";
/**
* 根据 parameters里面decrypt_param 的值进行参数解密,并把解密后的值替换原值
* @param parameters 参数集合
*/
default void decryptParams(Map<String, String> parameters) {
if (CollUtil.isNotEmpty(parameters)) {
//从 parameters 中获取 decrypt_param 参数值
String decryptParam = parameters.get(PARAM_KEY_DECRYPT_PARAM);
//如果参数decrypt_param有值,则进行参数解密
if (StrUtil.isNotEmpty(decryptParam)) {
String[] paramNames = decryptParam.split(SEPARATOR);
this.decrypt(paramNames, parameters);
}
}
}
/**
* 解密并更新参数值
* @param paramNames 需要解密的参数名
* @param parameters 参数集合(参数名:参数值)
*/
void decrypt(String[] paramNames, Map<String, String> parameters);
}
package com.central.oauth.handler.decryptParamHandler;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.central.oauth2.common.properties.AuthProperties;
import com.central.oauth2.common.properties.SecurityProperties;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 使用rsa算法对参数进行解密
*
* @author zlt
* @version 1.0
* @date 2022/12/29
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Service
public class RsaDecryptParamHandler implements IDecryptParamHandler {
private final AuthProperties authProperties;
public RsaDecryptParamHandler(SecurityProperties securityProperties) {
this.authProperties = securityProperties.getAuth();
}
@Override
public void decrypt(String[] paramNames, Map<String, String> parameters) {
RSA rsaTools = SecureUtil.rsa(authProperties.getDecryptParamPrivateKey(), null);
String value;
for (String param : paramNames) {
value = parameters.get(param);
if (StrUtil.isNotEmpty(value)) {
//解密
value = this.decrypt(rsaTools, value, param);
//更新参数为解密后的值
parameters.put(param, value);
}
}
}
private String decrypt(RSA rsaTools, String value, String param) {
try {
return rsaTools.decryptStr(value, KeyType.PrivateKey);
} catch (Exception e) {
throw new OAuth2Exception("参数 " + param + " 解密失败!");
}
}
}
package com.central.oauth2.common.util;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
/**
* TODO
*
* @author zlt
* @version 1.0
* @date 2023/1/30
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@RunWith(SpringRunner.class)
public class RsaUtilsTest {
/**
* 私钥
*/
private final static String PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDq7iw/3r2Fk/sFQR4BcmWrnASZnYIhlTj7kkANjwi6bnmoZoTmpcTAxpX4zYcVZTg9lsd8f5EYQgzCOQBFGiT3eSsWcm67BOMvCDJRKwqbkzu/cSTzN2qzjvi/Wo7GoToGYfP1Al+CcC0VjHATJVGhDXb4gCGk7MNTevPTZVHTmQYKuAZTqzPEO2npxD670AIY/L+4p0hDoftoz+jEzI+XAr0ffyeLovFqLurnqqnoXWnt2vGHwJYlnePQ2JwHlk+c4y2sYvmV+eJ8cGMH4IMle/yR99jTPAvcn4uufIVukp414wlmnKShhbzk93P7xacT0oYwzcR454P9Bf858x0VAgMBAAECggEBAJxK94VGWi+T01wbhirQQHN6yFSqRPiyncY/9f0PO29MMAOosKIBhnP5qaxsj4HcZR4UQYLCG3VX+8T6xwMx8YXyRogYeTJSfhG8Ej2NtPDrcsRaMYrdQ09RvosPZA0hFclJQVOu0HumxVegpq8WFMhgfNW16KwgF5JiKfRpY5aw4NDWZFmdNExdymrWPheI8pWBq/U+l8oqrekhbiEKXM2UXmLlKTS9Nk46LRYwaaiDW8JEFuPdx0cnakb+ecCXGd/8Cc8Hxn/mLyvqS1cWHT3J+lXRkfcnNnrJTR9qhf9l077XBMJqVckFEpK4kKbXHZd957ISAxq48Tm+xMX9KAECgYEA995szPToU0BxTTtOD4Z4c5JvbURQEcDQl/dB+qCQnu/orW5ZWv4++lHq2SZPjzbt7M8OaoRN8A5zYcNrYe4kBhLOLqHdaS1yUGIIjAejEAJplR5GqI3T5qzaLjpyiUZpO0mOcwAazCevnSXH6uO5jP0sjwxwaXz4OsTcpHIXHqECgYEA8qMXhh+G88+vTELL/2dHhtTIf7IAJLQ37c1Xrm6uwOHPfiDr256Lc4EzF8QAQqlHoYm1jRK7xDfFymY/SJKJVhYehWlNilnMuDuDOqseC/Zn2KgjMSjLLVkbp25DcpAu6SSiWlBvemrV3jivX/MU0BFp8HjbrlUcl12lRtYgrfUCgYB+iN2iA6RWW597fbrr0gnLdgXMEgOODJBwA5l7CFzLxk1Ru/OBsCkWQJtTH2ueALyVF16UodXnpnjgf5Jh++AH+bGnvJn7B2hEAMe8NGnZ0mFz7nDDuyNhrvvyfYPa8EboLTS7IGKNtfTAlHjqQDaI8vW8UO1R7KoL1lOM33FOAQKBgQDt/Z6jReU+3CUbbiFeANWdoLSQ2+1cExEQxWsNgy8Rreux0WTG4/nwb3fIBc4jlJrYDZTwLMHTssjkv+muq1zd/ZAuV51g6LfutSEAuLseDLDLSBBMtbCkaFTBo1uw0U/SCsbcQy01K/leoMcUG//8HjiFUGZZ1s3WgloM4xbmyQKBgAipgnoEyzvUfe2OMOc5ARGNSGZG4JGTGCyfnrYvYfffWpAokklHOkZMumeSWJXkx5F+MgJd9fxBK9S57PZ09gWkoeSVg0xcz5QMjh8BswfCdyet/CXQtwIfK0Wf1gWdAxC6vvv3DQ7zXbTlvqMdVOFzCKlocCYkzWMvIsejWXnW";
/**
* 公钥
*/
private final static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6u4sP969hZP7BUEeAXJlq5wEmZ2CIZU4+5JADY8Ium55qGaE5qXEwMaV+M2HFWU4PZbHfH+RGEIMwjkARRok93krFnJuuwTjLwgyUSsKm5M7v3Ek8zdqs474v1qOxqE6BmHz9QJfgnAtFYxwEyVRoQ12+IAhpOzDU3rz02VR05kGCrgGU6szxDtp6cQ+u9ACGPy/uKdIQ6H7aM/oxMyPlwK9H38ni6Lxai7q56qp6F1p7drxh8CWJZ3j0NicB5ZPnOMtrGL5lfnifHBjB+CDJXv8kffY0zwL3J+LrnyFbpKeNeMJZpykoYW85Pdz+8WnE9KGMM3EeOeD/QX/OfMdFQIDAQAB";
private static RSA rsaTools;
@BeforeClass
public static void init() {
rsaTools = SecureUtil.rsa(PRIVATE_KEY, PUBLIC_KEY);
}
@Test
public void testDecrypt() {
String value = "admin";
String result = rsaTools.encryptBcd(value, KeyType.PublicKey);
System.out.println(result);
}
@Test
public void testEncrypt() {
String value = "8A806900A16294BF11F3D0455ADE2759CCC8C52F0BB5DEF731A0E5F596203401899B545B36E7072EC4CC1AA2FDE7481589783D555D36EDDDC19587D62B6AB39A6478FF75600F2B3671816D33C2AF6776F3865838EA2D90060E01C014B6F0DAE7D0D09EC80FF3F2ABFE5F12F111A72390A0083534789F49D9CA36CF39D071622B75C5B5F2BEC609F7C7EE53E324FA0443AC31BE40FF9B6693AE5BEAC0BFDC677794E7A5B503B3A3F571DD6AB5169598F5FC59D63EF60E572FFDF3CA2DCB818A2448C6E25CC46B17CBB232B0F46BC05C916EEB05E9C852B0729C3DE28C7FD679B89E370FB829ACB4485A7346E50AA06655A5A9DFDA5685145A6142A04ACF72D689";
String result = rsaTools.decryptStr(value, KeyType.PrivateKey);
System.out.println(result);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册