commit
This commit is contained in:
@@ -67,4 +67,9 @@ public class RedisConstant {
|
|||||||
* 数据接口锁前缀
|
* 数据接口锁前缀
|
||||||
*/
|
*/
|
||||||
public static final String DATE_CENTER_PREFIX = PLATFORM_REDIS_PREFIX + "datacenter:token:";
|
public static final String DATE_CENTER_PREFIX = PLATFORM_REDIS_PREFIX + "datacenter:token:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据接口锁前缀
|
||||||
|
*/
|
||||||
|
public static final String RSA_KEY_PREFIX = PLATFORM_REDIS_PREFIX + "rsa:private:";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.budwk.app.base.utils;
|
||||||
|
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.*;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName RsaUtils
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/10/29 9:56
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
public class RsaUtils {
|
||||||
|
static {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyPair generateKeyPair() throws Exception {
|
||||||
|
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "BC");
|
||||||
|
keyGen.initialize(2048);
|
||||||
|
return keyGen.generateKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPublicKeyBase64(PublicKey publicKey) {
|
||||||
|
return Base64.getEncoder().encodeToString(publicKey.getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPrivateKeyBase64(PrivateKey privateKey) {
|
||||||
|
return Base64.getEncoder().encodeToString(privateKey.getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String decrypt(String encryptedBase64, PrivateKey privateKey) throws Exception {
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
|
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedBase64));
|
||||||
|
return new String(decrypted, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
|
|||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.budwk.app.base.annotation.SLog;
|
import com.budwk.app.base.annotation.SLog;
|
||||||
|
import com.budwk.app.base.exception.BaseException;
|
||||||
import com.budwk.app.base.page.Pagination;
|
import com.budwk.app.base.page.Pagination;
|
||||||
import com.budwk.app.base.param.PageForm;
|
import com.budwk.app.base.param.PageForm;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
@@ -17,6 +18,12 @@ import com.google.common.net.HttpHeaders;
|
|||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.pdfbox.Loader;
|
||||||
|
import org.apache.pdfbox.cos.COSDictionary;
|
||||||
|
import org.apache.pdfbox.cos.COSName;
|
||||||
|
import org.apache.pdfbox.io.RandomAccessRead;
|
||||||
|
import org.apache.pdfbox.io.RandomAccessReadBuffer;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
@@ -26,8 +33,10 @@ import org.nutz.mvc.upload.UploadAdaptor;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@IocBean
|
@IocBean
|
||||||
@@ -62,6 +71,20 @@ public class SysFileController {
|
|||||||
if (file == null) {
|
if (file == null) {
|
||||||
return Result.error("文件内容为空");
|
return Result.error("文件内容为空");
|
||||||
}
|
}
|
||||||
|
String submittedFileName = file.getSubmittedFileName();
|
||||||
|
if (submittedFileName.contains("pdf")) {
|
||||||
|
try {
|
||||||
|
byte[] pdfBytes = Files.readAllBytes(file.getFile().toPath());
|
||||||
|
if (isPdfContainsJavaScript(pdfBytes)) {
|
||||||
|
//throw new BaseException("禁止上传包含 JavaScript 的 PDF 文件");
|
||||||
|
throw new BaseException("系统检测到此 PDF 文件具有一定危险性");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("PDF 安全扫描失败,文件可能损坏", e);
|
||||||
|
// 可选择拒绝或放行(建议拒绝)
|
||||||
|
throw new BaseException("PDF 文件解析失败,请上传合法文件");
|
||||||
|
}
|
||||||
|
}
|
||||||
String id = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), file);
|
String id = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), file);
|
||||||
return Result.success().addData(id);
|
return Result.success().addData(id);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -207,4 +230,33 @@ public class SysFileController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPdfContainsJavaScript(byte[] pdfBytes) throws IOException {
|
||||||
|
try (PDDocument document = Loader.loadPDF(new RandomAccessReadBuffer(pdfBytes))) {
|
||||||
|
COSDictionary catalog = document.getDocumentCatalog().getCOSObject();
|
||||||
|
|
||||||
|
// 1. 检查 /Names -> /JavaScript
|
||||||
|
if (catalog.containsKey(COSName.NAMES)) {
|
||||||
|
COSDictionary names = (COSDictionary) catalog.getDictionaryObject(COSName.NAMES);
|
||||||
|
if (names != null && names.containsKey(COSName.JAVA_SCRIPT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 检查 /OpenAction(可能指向 JS action)
|
||||||
|
if (catalog.containsKey(COSName.OPEN_ACTION)) {
|
||||||
|
var openAction = catalog.getDictionaryObject(COSName.OPEN_ACTION);
|
||||||
|
if (openAction instanceof COSDictionary) {
|
||||||
|
COSDictionary actionDict = (COSDictionary) openAction;
|
||||||
|
if (COSName.JAVA_SCRIPT.equals(actionDict.getDictionaryObject(COSName.S))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. (可选)检查 AcroForm 中的 JS(更复杂,通常用于表单)
|
||||||
|
// 可根据安全需求决定是否实现
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.budwk.app.base.enums.LoginType;
|
|||||||
import com.budwk.app.base.exception.BaseException;
|
import com.budwk.app.base.exception.BaseException;
|
||||||
import com.budwk.app.base.interceptor.sLog.SLogService;
|
import com.budwk.app.base.interceptor.sLog.SLogService;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.base.utils.RsaUtils;
|
||||||
import com.budwk.app.sys.models.Sys_log;
|
import com.budwk.app.sys.models.Sys_log;
|
||||||
import com.budwk.app.sys.models.Sys_user;
|
import com.budwk.app.sys.models.Sys_user;
|
||||||
import com.budwk.app.sys.services.SysUserService;
|
import com.budwk.app.sys.services.SysUserService;
|
||||||
@@ -39,6 +40,15 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
@IocBean
|
@IocBean
|
||||||
@@ -84,15 +94,25 @@ public class SysLoginController {
|
|||||||
@At("/doLogin")
|
@At("/doLogin")
|
||||||
@Ok("json")
|
@Ok("json")
|
||||||
@ApiOperation("用户本地账号密码登录")
|
@ApiOperation("用户本地账号密码登录")
|
||||||
public Object doLogin(@Param("username") String username, @Param("password") String password, @Param("platformKey") String captchaKey, @Param("platformCaptcha") String captchaCode, HttpServletRequest req, HttpServletResponse response, HttpSession session) {
|
public Object doLogin(@Param("username") String username,
|
||||||
|
@Param("password") String password,
|
||||||
|
@Param("platformKey") String captchaKey,
|
||||||
|
@Param("platformCaptcha") String captchaCode,
|
||||||
|
@Param("keyId") String keyId,
|
||||||
|
HttpServletRequest req,
|
||||||
|
HttpServletResponse response,
|
||||||
|
HttpSession session) {
|
||||||
if (StrUtil.isBlank(username)) {
|
if (StrUtil.isBlank(username)) {
|
||||||
return Result.error("用户名不能为空");
|
return Result.error("用户名不能为空");
|
||||||
}
|
}
|
||||||
if (StrUtil.isBlank(password)) {
|
if (StrUtil.isBlank(password)) {
|
||||||
return Result.error("密码不能为空");
|
return Result.error("密码不能为空");
|
||||||
}
|
}
|
||||||
|
if (StrUtil.isBlank(keyId)) {
|
||||||
|
return Result.error("参数缺失");
|
||||||
|
}
|
||||||
|
|
||||||
String lockKey = RedisConstant.USER_LOGIN_LOCK_PREFIX + username;
|
String lockKey = RedisConstant.USER_LOGIN_LOCK_PREFIX + username;
|
||||||
int errCount = Convert.toInt(StrUtil.blankToDefault(redisService.get(lockKey), "0"));
|
int errCount = Convert.toInt(StrUtil.blankToDefault(redisService.get(lockKey), "0"));
|
||||||
log.info("用户名:" + username + "登录失败次数:" + errCount);
|
log.info("用户名:" + username + "登录失败次数:" + errCount);
|
||||||
|
|
||||||
@@ -108,8 +128,14 @@ public class SysLoginController {
|
|||||||
return Result.error(e.getMessage());
|
return Result.error(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户名密码校验
|
// 解密密码
|
||||||
Sys_user user = sysUserService.loginByPassword(username, password);
|
String decryptPwd = validateService.decryptPwd(keyId, password);
|
||||||
|
if (decryptPwd == null) {
|
||||||
|
throw new BaseException("用户登录失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户名密码校验
|
||||||
|
Sys_user user = sysUserService.loginByPassword(username, decryptPwd);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new BaseException("用户登录失败");
|
throw new BaseException("用户登录失败");
|
||||||
}
|
}
|
||||||
@@ -234,4 +260,30 @@ public class SysLoginController {
|
|||||||
return Result.success(validateService.getCaptcha());
|
return Result.success(validateService.getCaptcha());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@At("/publicKey")
|
||||||
|
@Ok("json")
|
||||||
|
@ApiOperation("获取公钥")
|
||||||
|
public Object publicKey() {
|
||||||
|
try {
|
||||||
|
// 生成密钥对
|
||||||
|
KeyPair keyPair = RsaUtils.generateKeyPair();
|
||||||
|
String publicKeyStr = RsaUtils.getPublicKeyBase64(keyPair.getPublic());
|
||||||
|
String privateKeyStr = RsaUtils.getPrivateKeyBase64(keyPair.getPrivate());
|
||||||
|
|
||||||
|
// 生成 UUID 作为 keyId
|
||||||
|
String keyId = UUID.randomUUID().toString().replace("-", "");
|
||||||
|
|
||||||
|
// 私钥存入 Redis,5 分钟过期,也防止恶意刷密钥
|
||||||
|
redisService.setex(RedisConstant.RSA_KEY_PREFIX + keyId, 5 * 60, privateKeyStr);
|
||||||
|
|
||||||
|
// 返回给前端
|
||||||
|
return Result.success(Map.of(
|
||||||
|
"publicKey", publicKeyStr,
|
||||||
|
"keyId", keyId
|
||||||
|
));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("生成 RSA 密钥失败", e);
|
||||||
|
return Result.error("系统异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.budwk.app.web.commons.auth.service;
|
|||||||
|
|
||||||
import com.budwk.app.base.constant.RedisConstant;
|
import com.budwk.app.base.constant.RedisConstant;
|
||||||
import com.budwk.app.base.exception.BaseException;
|
import com.budwk.app.base.exception.BaseException;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.base.utils.RsaUtils;
|
||||||
import com.wf.captcha.ArithmeticCaptcha;
|
import com.wf.captcha.ArithmeticCaptcha;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.nutz.integration.jedis.RedisService;
|
import org.nutz.integration.jedis.RedisService;
|
||||||
@@ -11,6 +13,12 @@ import org.nutz.lang.Strings;
|
|||||||
import org.nutz.lang.random.R;
|
import org.nutz.lang.random.R;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
|
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author wizzer@qq.com
|
* @author wizzer@qq.com
|
||||||
*/
|
*/
|
||||||
@@ -96,4 +104,20 @@ public class ValidateService {
|
|||||||
redisService.del(RedisConstant.UCENTER_SMSCODE + mobile);
|
redisService.del(RedisConstant.UCENTER_SMSCODE + mobile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String decryptPwd(String keyId, String password) throws Exception {
|
||||||
|
// 从 Redis 获取私钥
|
||||||
|
String rsaKey = RedisConstant.RSA_KEY_PREFIX + keyId;
|
||||||
|
String privateKeyStr = redisService.get(rsaKey);
|
||||||
|
if (privateKeyStr == null) {
|
||||||
|
throw new BaseException("公钥已过期,请刷新登录页面");
|
||||||
|
}
|
||||||
|
// 删除私钥(一次性使用,防重放)
|
||||||
|
redisService.del(rsaKey);
|
||||||
|
// 解码私钥
|
||||||
|
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
|
||||||
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
|
||||||
|
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
|
||||||
|
// 解密密码
|
||||||
|
return RsaUtils.decrypt(password, privateKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -47,7 +47,7 @@ class PDFMenu extends BtnMenu {
|
|||||||
</a>`
|
</a>`
|
||||||
_this.editor.txt.html(html)
|
_this.editor.txt.html(html)
|
||||||
} else {
|
} else {
|
||||||
alert(response.data.msg + ',上传pdf失败,请联系管理员!')
|
alert(response.data.msg + ',上传pdf失败,请联系管理员!')
|
||||||
_this.clearInputFile()
|
_this.clearInputFile()
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
@@ -60,7 +60,9 @@ class PDFMenu extends BtnMenu {
|
|||||||
|
|
||||||
clearInputFile() {
|
clearInputFile() {
|
||||||
const obj = document.getElementById('fileInput');
|
const obj = document.getElementById('fileInput');
|
||||||
obj.outerHTML = obj.outerHTML
|
if(obj) {
|
||||||
|
obj.outerHTML = obj.outerHTML
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tryChangeActive() {
|
tryChangeActive() {
|
||||||
|
|||||||
@@ -31,9 +31,9 @@
|
|||||||
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css" />
|
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css" />
|
||||||
|
|
||||||
<!-- import Jquery -->
|
<!-- import Jquery -->
|
||||||
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
|
<script src="${base!}/assets/platform/plugins/jquery/jquery-high.min.js"></script>
|
||||||
<!-- pjax是异步加载html片段的工具,模拟前端路由机制 -->
|
<!-- pjax是异步加载html片段的工具,模拟前端路由机制 -->
|
||||||
<script src="${base!}/assets/platform/plugins/pjax/jquery.pjax.js"></script>
|
<script src="${base!}/assets/platform/plugins/pjax/jquery.pjax-high.min.js"></script>
|
||||||
<!-- nprogress 配合pjax使用 -->
|
<!-- nprogress 配合pjax使用 -->
|
||||||
<link rel="stylesheet" href="${base!}/assets/platform/plugins/nprogress/nprogress.css" />
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/nprogress/nprogress.css" />
|
||||||
<script src="${base!}/assets/platform/plugins/nprogress/nprogress.js"></script>
|
<script src="${base!}/assets/platform/plugins/nprogress/nprogress.js"></script>
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
<script src="https://vxeui.com/umd/xe-utils@3.5.30/dist/xe-utils.umd.min.js"></script>
|
<script src="https://vxeui.com/umd/xe-utils@3.5.30/dist/xe-utils.umd.min.js"></script>
|
||||||
<script src="https://vxeui.com/umd/vxe-pc-ui@3.1.25/lib/index.umd.min.js"></script>
|
<script src="https://vxeui.com/umd/vxe-pc-ui@3.1.25/lib/index.umd.min.js"></script>
|
||||||
<script src="https://vxeui.com/umd/vxe-table@3.9.0/lib/index.umd.min.js"></script>
|
<script src="https://vxeui.com/umd/vxe-table@3.9.0/lib/index.umd.min.js"></script>
|
||||||
|
l
|
||||||
<!-- 引入 form-create 和 designer -->
|
<!-- 引入 form-create 和 designer -->
|
||||||
<script src="${base!}/assets/platform/plugins/form-create/form-create.min.js"></script>
|
<script src="${base!}/assets/platform/plugins/form-create/form-create.min.js"></script>
|
||||||
<script src="${base!}/assets/platform/plugins/form-create/index.umd.js"></script>
|
<script src="${base!}/assets/platform/plugins/form-create/index.umd.js"></script>
|
||||||
@@ -92,6 +92,28 @@
|
|||||||
<script src="${base!}/assets/platform/js/util/autoShowError.js"></script>
|
<script src="${base!}/assets/platform/js/util/autoShowError.js"></script>
|
||||||
<script src="${base!}/assets/platform/plugins/fullcalendar/fullcalendar.min.js"></script>
|
<script src="${base!}/assets/platform/plugins/fullcalendar/fullcalendar.min.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 安全地冻结 Object.prototype(跳过不可配置属性)
|
||||||
|
(function () {
|
||||||
|
const badKeys = ['__proto__', 'constructor', 'prototype'];
|
||||||
|
for (const key of badKeys) {
|
||||||
|
if (key in Object.prototype) {
|
||||||
|
try {
|
||||||
|
delete Object.prototype[key];
|
||||||
|
} catch (e) {
|
||||||
|
// 忽略无法删除的属性(如 __proto__ 在现代浏览器中不可删除)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 冻结 Object.prototype(如果可能)
|
||||||
|
try {
|
||||||
|
Object.freeze(Object.prototype);
|
||||||
|
} catch (e) {
|
||||||
|
// 忽略错误(某些环境可能不允许)
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window._AMapSecurityConfig = {
|
window._AMapSecurityConfig = {
|
||||||
securityJsCode: "4fa1e1aeabba7eb9518129cf57ab17c1"
|
securityJsCode: "4fa1e1aeabba7eb9518129cf57ab17c1"
|
||||||
@@ -647,7 +669,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div style="height: 64px"></div>
|
<div style="height: 45px"></div>
|
||||||
|
|
||||||
<main class="v4-content">
|
<main class="v4-content">
|
||||||
<!-- 页面内容区域 -->
|
<!-- 页面内容区域 -->
|
||||||
|
|||||||
@@ -92,11 +92,35 @@
|
|||||||
<!-- import axios -->
|
<!-- import axios -->
|
||||||
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
|
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
|
||||||
<!-- import Jquery -->
|
<!-- import Jquery -->
|
||||||
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
|
<script src="${base!}/assets/platform/plugins/jquery/jquery-high.min.js"></script>
|
||||||
<!-- import SM2 -->
|
<!-- import SM2 -->
|
||||||
<script src="${base!}/assets/platform/plugins/sm-crypto/sm2.js"></script>
|
<script src="${base!}/assets/platform/plugins/sm-crypto/sm2.js"></script>
|
||||||
<!-- import commonUtil -->
|
<!-- import commonUtil -->
|
||||||
<script src="${base!}/assets/platform/js/util/commonUtil.js"></script>
|
<script src="${base!}/assets/platform/js/util/commonUtil.js"></script>
|
||||||
|
<!-- import jsencrypt-->
|
||||||
|
<script src="${base!}/assets/platform/plugins/jsencrypt/jsencrypt.min.js"></script>
|
||||||
|
<script>
|
||||||
|
// 安全地冻结 Object.prototype(跳过不可配置属性)
|
||||||
|
(function () {
|
||||||
|
const badKeys = ['__proto__', 'constructor', 'prototype'];
|
||||||
|
for (const key of badKeys) {
|
||||||
|
if (key in Object.prototype) {
|
||||||
|
try {
|
||||||
|
delete Object.prototype[key];
|
||||||
|
} catch (e) {
|
||||||
|
// 忽略无法删除的属性(如 __proto__ 在现代浏览器中不可删除)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 冻结 Object.prototype(如果可能)
|
||||||
|
try {
|
||||||
|
Object.freeze(Object.prototype);
|
||||||
|
} catch (e) {
|
||||||
|
// 忽略错误(某些环境可能不允许)
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
<script>
|
<script>
|
||||||
new Vue({
|
new Vue({
|
||||||
el: "#app",
|
el: "#app",
|
||||||
@@ -114,7 +138,11 @@
|
|||||||
password: [{ required: true, trigger: ["blur", "change"], message: "密码不能为空" }],
|
password: [{ required: true, trigger: ["blur", "change"], message: "密码不能为空" }],
|
||||||
platformCaptcha: [{ required: true, trigger: ["blur", "change"], message: "验证码不能为空" }]
|
platformCaptcha: [{ required: true, trigger: ["blur", "change"], message: "验证码不能为空" }]
|
||||||
},
|
},
|
||||||
loading: false
|
loading: false,
|
||||||
|
rasParams: {
|
||||||
|
publicKey: '',
|
||||||
|
keyId: '',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -127,13 +155,20 @@
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleLogin() {
|
handleLogin() {
|
||||||
this.$refs.loginForm.validate((valid) => {
|
this.$refs.loginForm.validate(async (valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
const { publicKey, keyId } = this.rasParams
|
||||||
|
// 加密密码
|
||||||
|
const encrypt = new JSEncrypt()
|
||||||
|
encrypt.setPublicKey(publicKey)
|
||||||
|
const encryptedPassword = encrypt.encrypt(this.loginForm.password)
|
||||||
axios
|
axios
|
||||||
.post("/platform/login/doLogin", null, {
|
.post("/platform/login/doLogin", null, {
|
||||||
params: {
|
params: {
|
||||||
...this.loginForm,
|
...this.loginForm,
|
||||||
password: window.btoa(this.loginForm.password)
|
//password: window.btoa(this.loginForm.password)
|
||||||
|
password: encryptedPassword,
|
||||||
|
keyId: keyId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
@@ -160,9 +195,16 @@
|
|||||||
console.log("cccccc")
|
console.log("cccccc")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
|
// 获取公钥
|
||||||
|
fetchPublicKey() {
|
||||||
|
axios.get("/platform/login/publicKey").then(res => {
|
||||||
|
this.rasParams = res.data.data
|
||||||
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
this.fetchPublicKey()
|
||||||
this.getCode()
|
this.getCode()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user