浏览代码

登录信息加密

master
zhaodengke 1年前
父节点
当前提交
d44f0e0f0e
共有 7 个文件被更改,包括 268 次插入7 次删除
  1. +2
    -2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/agentcenter/AgentCenterController.java
  2. +9
    -1
      ruoyi-admin/src/main/resources/application.yml
  3. +47
    -4
      ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
  4. +146
    -0
      ruoyi-common/src/main/java/com/ruoyi/common/exception/ASSERT.java
  5. +30
    -0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/SecretUtils.java
  6. +13
    -0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
  7. +21
    -0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java

+ 2
- 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/agentcenter/AgentCenterController.java 查看文件

@@ -36,7 +36,7 @@ public class AgentCenterController extends BaseController
NSSDKServer server;
NSReportObject<NSContractionMessage> recv;

NSSDK.InitServer(RuoYiConfig.Secret.privateKey);
NSSDK.InitServer(RuoYiConfig.AgentCenter.privateKey);
server = NSSDK.InstanceServer();
recv = server.Recv(request, NSContractionMessage.class);

@@ -49,7 +49,7 @@ public class AgentCenterController extends BaseController
NSSDKServer server;
Session<?> session;

NSSDK.InitServer(RuoYiConfig.Secret.privateKey);
NSSDK.InitServer(RuoYiConfig.AgentCenter.privateKey);
server = NSSDK.InstanceServer();
try
{


+ 9
- 1
ruoyi-admin/src/main/resources/application.yml 查看文件

@@ -130,8 +130,16 @@ xss:
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*

# 传输加密(公钥,私钥)
secret:
# 是否启用
enabled: true
# 是否兼容不加密明文
compat: false
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y=

agentcenter:
disabled: false # UNUSED
# 客户端公钥
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==


+ 47
- 4
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java 查看文件

@@ -1,5 +1,6 @@
package com.ruoyi.common.config;

import com.ruoyi.common.utils.SecretUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@@ -137,14 +138,42 @@ public class RuoYiConfig


@Component
@ConfigurationProperties(prefix = "secret")
public static class Secret {
@ConfigurationProperties(prefix = "agentcenter")
public static class AgentCenter {
public static Boolean disabled;
public static String publicKey;
public static String privateKey;

public void setDisabled(Boolean disabled) {
Secret.disabled = disabled;
AgentCenter.disabled = disabled;
}

public void setPublicKey(String publicKey) {
AgentCenter.publicKey = publicKey;
}

public void setPrivateKey(String privateKey) {
AgentCenter.privateKey = privateKey;
}

public static boolean isDisabled() {
return null != AgentCenter.disabled /*默认加密*/ && AgentCenter.disabled;
}
}
@Component
@ConfigurationProperties(prefix = "secret")
public static class Secret {
public static Boolean enabled;
public static String publicKey;
public static String privateKey;
public static Boolean compat;

public void setCompat(Boolean compat) {
Secret.compat = compat;
}

public void setEnabled(Boolean enabled) {
Secret.enabled = enabled;
}

public void setPublicKey(String publicKey) {
@@ -156,7 +185,21 @@ public class RuoYiConfig
}

public static boolean isDisabled() {
return null != Secret.disabled /*默认加密*/ && Secret.disabled;
return null == Secret.enabled /*默认不加密*/ || !Secret.enabled;
}

public static boolean isCompat() {
return null != Secret.compat /*默认不兼容*/ && Secret.compat;
}

// 私钥解密
public static String decrypt(String inStr) {
try {
return SecretUtils.decrypt(inStr, Secret.privateKey, StandardCharsets.UTF_8.name());
} catch (Exception e) {
//e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}

+ 146
- 0
ruoyi-common/src/main/java/com/ruoyi/common/exception/ASSERT.java 查看文件

@@ -0,0 +1,146 @@
package com.ruoyi.common.exception;

import java.util.Map;
import java.util.Objects;

/**
* 断言异常
*
* @author zhao
*/
public final class ASSERT extends RuntimeException
{
private static final long serialVersionUID = 1L;

public final String message;

public ASSERT(String message)
{
this.message = message;
}

@Override
public String getMessage()
{
return message;
}

public static String Output(ASSERT e)
{
StringBuilder sb = new StringBuilder();
sb.append(e.message);
StackTraceElement[] stackTrace = e.getStackTrace();
if(null != stackTrace)
{
for(int i = 0; i < stackTrace.length; i++)
{
StackTraceElement st = stackTrace[i];
if(st.getClassName().startsWith("com.ruoyi."))
{
sb.append("\n").append("\t").append(i).append(": ").append(st.toString());
}
}
}
return sb.toString();
}

public static void THROW(String message, Object...args)
{
throw new ASSERT(null != message ? String.format(message, args) : "断言失败");
}

public static void EXP(boolean expression, String errorMsgTemplate, Object... params) throws ASSERT {
if(!expression)
THROW(errorMsgTemplate, params);
}
public static void EXP(boolean expression) throws ASSERT {
EXP(expression, "断言表达式为假");
}

public static void TRUE(boolean expression, String errorMsgTemplate, Object... params) throws ASSERT {
if(!expression)
THROW(errorMsgTemplate, params);
}

public static void TRUE(boolean expression) throws ASSERT {
TRUE(expression, "[断言失败] - 表达式必须为true");
}

public static void FALSE(boolean expression, String errorMsgTemplate, Object... params) throws ASSERT {
if(expression)
THROW(errorMsgTemplate, params);
}

public static void FALSE(boolean expression) throws ASSERT {
FALSE(expression, "[断言失败] - 表达式必须false");
}

public static void NULL(Object object, String errorMsgTemplate, Object... params) throws ASSERT {
if(Objects.nonNull(object))
THROW(errorMsgTemplate, params);
}

public static void NULL(Object object) throws ASSERT {
NULL(object, "[断言失败] - 对象必须为null");
}

public static <T> T NONNULL(T object, String errorMsgTemplate, Object... params) throws ASSERT {
if(Objects.isNull(object))
THROW(errorMsgTemplate, params);
return object;
}

public static <T> T NONNULL(T object) throws ASSERT {
return NONNULL(object, "[断言失败] - 对象必须非null");
}

public static String NOTEMPTY(String text, String errorMsgTemplate, Object... params) throws ASSERT {
if(null == text || text.isEmpty() || text.trim().isEmpty())
THROW(errorMsgTemplate, params);
return text;
}

public static String NOTEMPTY(String text) throws ASSERT {
return NOTEMPTY(text, "[断言失败] - 字符串必须有非空字符数");
}

public static String EMPTY(String text, String errorMsgTemplate, Object... params) throws ASSERT {
if(null != text && !text.isEmpty() && !text.trim().isEmpty())
THROW(errorMsgTemplate, params);
return text;
}

public static String EMPTY(String text) throws ASSERT {
return EMPTY(text, "[断言失败] - 字符串必须不能包含非空字符");
}

public static <T> T[] NOTEMPTY(T[] array, String errorMsgTemplate, Object... params) throws ASSERT {
if(null == array || array.length == 0)
THROW(errorMsgTemplate, params);
return array;
}

public static <T> T[] NOTEMPTY(T[] array) throws ASSERT {
return NOTEMPTY(array, "[断言失败] - 数组必须非空");
}

public static <T> Iterable<T> NOTEMPTY(Iterable<T> collection, String errorMsgTemplate, Object... params) throws ASSERT {
if(null == collection || !collection.iterator().hasNext() )
THROW(errorMsgTemplate, params);
return collection;
}

public static <T> Iterable<T> NOTEMPTY(Iterable<T> collection) throws ASSERT {
return NOTEMPTY(collection, "[断言失败] - 集合容器必须非空");
}

public static <K, V> Map<K, V> NOTEMPTY(Map<K, V> map, String errorMsgTemplate, Object... params) throws ASSERT {
if(null == map || map.isEmpty() )
THROW(errorMsgTemplate, params);
return map;
}

public static <K, V> Map<K, V> NOTEMPTY(Map<K, V> map) throws ASSERT {
return NOTEMPTY(map, "[断言失败] - 关联容器必须非空");
}
}

+ 30
- 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/SecretUtils.java 查看文件

@@ -0,0 +1,30 @@
package com.ruoyi.common.utils;

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;

/**
* 密钥工具类
*
* @author nsgk
*/
public class SecretUtils {

public static String decrypt(String str, String privateKey, String...codec) throws Exception {
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str);
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
//这里直接new String() , 不用传输,为了直接查看解密后的明文(base64加密后看不懂)
String outStr = codec.length > 0 ? new String(cipher.doFinal(inputByte), codec[0]) : new String(cipher.doFinal(inputByte));
// byte[] decode = Base64.getDecoder().decode(inputByte); base64编码后的明文
return outStr;
}
}

+ 13
- 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java 查看文件

@@ -1,6 +1,8 @@
package com.ruoyi.framework.web.exception;

import javax.servlet.http.HttpServletRequest;

import com.ruoyi.common.exception.ASSERT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
@@ -111,4 +113,15 @@ public class GlobalExceptionHandler
{
return AjaxResult.error("演示模式,不允许操作");
}

/**
* 拦截断言异常: 不输出异常栈
*/
@ExceptionHandler(ASSERT.class)
public AjaxResult handleAssertFail(ASSERT e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常: {}.", requestURI, ASSERT.Output(e));
return AjaxResult.error(e.getMessage());
}
}

+ 21
- 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java 查看文件

@@ -1,6 +1,9 @@
package com.ruoyi.framework.web.service;

import javax.annotation.Resource;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.exception.ASSERT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
@@ -52,6 +55,23 @@ public class SysLoginService
@Autowired
private ISysConfigService configService;

private String D(String inStr)
{
if(RuoYiConfig.Secret.isDisabled())
return inStr;
try
{
return RuoYiConfig.Secret.decrypt(inStr);
}
catch(Exception e)
{
if(RuoYiConfig.Secret.isCompat())
return inStr;
else
throw new ASSERT("无效登录凭据");
}
}

/**
* 登录验证
*
@@ -63,6 +83,7 @@ public class SysLoginService
*/
public String login(String username, String password, String code, String uuid)
{
username = D(username); password = D(password);
// 验证码校验
validateCaptcha(username, code, uuid);
// 登录前置校验


正在加载...
取消
保存