Merge remote-tracking branch 'origin/master'
This commit is contained in:
+20
-5
@@ -1,5 +1,7 @@
|
||||
package com.jero.common.util;
|
||||
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
import cn.hutool.crypto.asymmetric.RSA;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.jero.common.constant.CommonConstant;
|
||||
import com.jero.common.constant.DataBaseConstant;
|
||||
@@ -10,14 +12,16 @@ import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -219,6 +223,17 @@ public class CommonUtils {
|
||||
boolean isExists = fileNameList.stream().anyMatch(name -> fileName.substring(0,fileName.lastIndexOf('.')).contains(name)||fileName.substring(fileName.lastIndexOf('.')).equals(name));
|
||||
return isExists;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA 使用私钥解密
|
||||
* @date 2021/4/15 16:11
|
||||
* @param str 待解密的字符串
|
||||
* @param RSAPrivateKey 私钥
|
||||
* @return String 解密后的字符串
|
||||
*/
|
||||
public static String decryptBtRsaPriKey(String str,String RSAPrivateKey) throws Exception {
|
||||
RSA rsa = new RSA(RSAPrivateKey, null);
|
||||
byte[] decrypt = rsa.decrypt(str, KeyType.PrivateKey);
|
||||
return new String(decrypt);
|
||||
}
|
||||
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
package com.jero.config;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.jero.common.api.vo.Result;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 描述:跨站过滤器
|
||||
*
|
||||
* @Author: 马志朝
|
||||
* @Date: 2021/4/16 14:09
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class CsrfFilter implements Filter {
|
||||
/**
|
||||
* LOGGER
|
||||
*/
|
||||
private static final Log LOGGER = LogFactory.getLog(CsrfFilter.class);
|
||||
|
||||
/**
|
||||
* 白名单
|
||||
*/
|
||||
private List<String> whiteUrls = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* size
|
||||
*/
|
||||
private int size = 0;
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
FileInputStream fis = null;
|
||||
InputStreamReader isr = null;
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
File file = ResourceUtils.getFile("classpath:whiteUrls.txt");
|
||||
fis = new FileInputStream(file);
|
||||
isr = new InputStreamReader(fis);
|
||||
br = new BufferedReader(isr);
|
||||
String url = null;
|
||||
while((url = br.readLine()) != null){
|
||||
whiteUrls.add(url);
|
||||
}
|
||||
size = whiteUrls.size();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(fis!=null){
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if(isr!=null){
|
||||
try {
|
||||
isr.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if(br!=null){
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
|
||||
try {
|
||||
HttpServletRequest req = (HttpServletRequest) request;
|
||||
HttpServletResponse res = (HttpServletResponse) response;
|
||||
// 获取请求url地址
|
||||
String url = req.getRequestURL().toString();
|
||||
// 获取来源
|
||||
String referurl = req.getHeader("Referer");
|
||||
if(isWhiteReq(referurl)){
|
||||
chain.doFilter(request, response);
|
||||
}else{
|
||||
String log = "";
|
||||
String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
|
||||
String ip = getIp(req);
|
||||
log = "跨站请求---->>>" + ip + "||" + date + "||" + referurl + "||" + url;
|
||||
LOGGER.warn(log);
|
||||
//发送错误信息
|
||||
JSONObject json = JSONUtil.parseObj(Result.error("监测到跨站请求,请求失败"), false);
|
||||
res.setCharacterEncoding("UTF-8");
|
||||
res.setContentType("application/json; charset=utf-8");
|
||||
PrintWriter out = res.getWriter();
|
||||
out.append(json.toStringPretty());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("doFilter", e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 判断是否是白名单
|
||||
*/
|
||||
private boolean isWhiteReq(String referUrl) {
|
||||
if (referUrl == null || "".equals(referUrl) || size == 0) {
|
||||
return true;
|
||||
} else {
|
||||
String refHost = "";
|
||||
referUrl = referUrl.toLowerCase();
|
||||
if (referUrl.startsWith("http://")) {
|
||||
refHost = referUrl.substring(7);
|
||||
} else if (referUrl.startsWith("https://")) {
|
||||
refHost = referUrl.substring(8);
|
||||
}
|
||||
for (String urlTemp : whiteUrls) {
|
||||
if (refHost.contains(urlTemp.toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 获取登录用户IP地址
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public String getIp(HttpServletRequest request) {
|
||||
String ip = request.getHeader("x-forwarded-for");
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
if (ip.equals("0:0:0:0:0:0:0:1")) {
|
||||
ip = "localhost";
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
}
|
||||
}
|
||||
+1
@@ -73,6 +73,7 @@ public class ShiroConfig {
|
||||
filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录
|
||||
filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
|
||||
filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
|
||||
filterChainDefinitionMap.put("/sys/getRSAPublicKey", "anon"); //获取RSA公钥接口排除
|
||||
filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
|
||||
filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
|
||||
filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
|
||||
|
||||
+20
-22
@@ -1,7 +1,7 @@
|
||||
package com.jero.modules.system.controller;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.RSA;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyuncs.exceptions.ClientException;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
@@ -33,7 +33,9 @@ import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.security.*;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -71,11 +73,12 @@ public class LoginController {
|
||||
Result<JSONObject> result = new Result<JSONObject>();
|
||||
String username = sysLoginModel.getUsername();
|
||||
String password = sysLoginModel.getPassword();
|
||||
String rsaPublicKey = sysLoginModel.getRsaPublicKey();
|
||||
String rsaPrivateKey = String.valueOf(redisUtil.get(rsaPublicKey));
|
||||
//update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题
|
||||
//前端密码加密,后端进行密码解密
|
||||
//password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密
|
||||
//update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题
|
||||
|
||||
//update-begin-author:taoyan date:20190828 for:校验验证码
|
||||
String captcha = sysLoginModel.getCaptcha();
|
||||
if(captcha==null){
|
||||
@@ -90,8 +93,13 @@ public class LoginController {
|
||||
result.error500("验证码错误");
|
||||
return result;
|
||||
}
|
||||
//update-end-author:taoyan date:20190828 for:校验验证码
|
||||
|
||||
try {
|
||||
//解密获取密码和用户名
|
||||
password = CommonUtils.decryptBtRsaPriKey(password, rsaPrivateKey);
|
||||
username = CommonUtils.decryptBtRsaPriKey(username, rsaPrivateKey);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//1. 校验用户是否有效
|
||||
//update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false
|
||||
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
@@ -119,7 +127,7 @@ public class LoginController {
|
||||
// 重试登录次数加一
|
||||
retryCount++;
|
||||
if( retryCount == 1){
|
||||
redisUtil.set(RETRY_LOGIN_PREFIX + username,retryCount, 60 * 30);
|
||||
redisUtil.set(RETRY_LOGIN_PREFIX + username,retryCount,60 * 30);
|
||||
}else {
|
||||
redisUtil.set(RETRY_LOGIN_PREFIX + username,retryCount,redisUtil.getExpire(RETRY_LOGIN_PREFIX + username));
|
||||
}
|
||||
@@ -534,24 +542,14 @@ public class LoginController {
|
||||
* @param
|
||||
* @return com.jero.common.api.vo.Result<java.lang.String>
|
||||
*/
|
||||
@ApiOperation("获取RSA公钥")
|
||||
@GetMapping("/getRSAPublicKey")
|
||||
public Result<String> getRSAPublicKey(){
|
||||
KeyPairGenerator keyPairGenerator = null;
|
||||
try {
|
||||
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
assert keyPairGenerator != null;
|
||||
KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||
// 得到私钥
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
// 得到公钥
|
||||
PublicKey publicKey = keyPair.getPublic();
|
||||
//base64编码
|
||||
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded());
|
||||
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());
|
||||
RSA rsa = new RSA();
|
||||
String privateKeyBase64 = rsa.getPrivateKeyBase64();
|
||||
String publicKeyBase64 = rsa.getPublicKeyBase64();
|
||||
//存到redis key为公钥 value为私钥
|
||||
redisUtil.set(publicKeyBase64, privateKeyBase64, 60 * 60L);
|
||||
redisUtil.set(publicKeyBase64, privateKeyBase64, 60L);
|
||||
Result<String> result = new Result<>();
|
||||
result.setResult(publicKeyBase64);
|
||||
return result;
|
||||
|
||||
+6
-6
@@ -19,8 +19,8 @@ public class SysLoginModel {
|
||||
private String captcha;
|
||||
@ApiModelProperty(value = "验证码key")
|
||||
private String checkKey;
|
||||
@ApiModelProperty(value ="RSA公钥")
|
||||
private String RSAPublicKey;
|
||||
@ApiModelProperty(value = "RSA公钥")
|
||||
private String rsaPublicKey;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
@@ -54,11 +54,11 @@ public class SysLoginModel {
|
||||
this.checkKey = checkKey;
|
||||
}
|
||||
|
||||
public String getRSAPublicKey() {
|
||||
return RSAPublicKey;
|
||||
public String getRsaPublicKey() {
|
||||
return rsaPublicKey;
|
||||
}
|
||||
|
||||
public void setRSAPublicKey(String RSAPublicKey) {
|
||||
this.RSAPublicKey = RSAPublicKey;
|
||||
public void setRsaPublicKey(String rsaPublicKey) {
|
||||
this.rsaPublicKey = rsaPublicKey;
|
||||
}
|
||||
}
|
||||
Generated
+5
@@ -9570,6 +9570,11 @@
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"dev": true
|
||||
},
|
||||
"jsencrypt": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.1.0.tgz",
|
||||
"integrity": "sha512-A4fIgyPN38G7wwB5t1Vkpi+w7j/nHKdradl/k9/GQqwAsxJqAJ55j3P5rWO3dvjhzOyWKOmK//WwzPO+o6gW0g=="
|
||||
},
|
||||
"jsesc": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"enquire.js": "^2.1.6",
|
||||
"js-base64": "^3.6.0",
|
||||
"js-cookie": "^2.2.0",
|
||||
"jsencrypt": "^3.0.0-rc.1",
|
||||
"lodash.get": "^4.4.2",
|
||||
"lodash.pick": "^4.4.0",
|
||||
"md5": "^2.2.1",
|
||||
|
||||
@@ -71,4 +71,19 @@ export function thirdLogin(token,thirdType) {
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取RSA公钥
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getRSAPublicKey() {
|
||||
return axios({
|
||||
url: `/sys/getRSAPublicKey`,
|
||||
method: 'get',
|
||||
timeout: 5000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -182,6 +182,9 @@
|
||||
import { ACCESS_TOKEN ,ENCRYPTED_STRING} from "@/store/mutation-types"
|
||||
import { putAction,postAction,getAction } from '@/api/manage'
|
||||
import { USER_INFO } from "@/store/mutation-types"
|
||||
import {getRSAPublicKey} from '@/api/login.js'
|
||||
const Base64 = require('js-base64').Base64
|
||||
import {JSEncrypt} from 'jsencrypt'
|
||||
|
||||
export default {
|
||||
components: {},
|
||||
@@ -211,6 +214,7 @@
|
||||
currdatetime:'',
|
||||
randCodeImage:'',
|
||||
requestCodeSuccess:false,
|
||||
rsaPublicKey:''
|
||||
}
|
||||
},
|
||||
created () {
|
||||
@@ -218,6 +222,7 @@
|
||||
Vue.ls.remove(ACCESS_TOKEN)
|
||||
this.getRouterData();
|
||||
this.handleChangeCheckCode();
|
||||
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['Login', 'Logout', 'PhoneLogin']),
|
||||
@@ -236,14 +241,19 @@
|
||||
that.loginBtn = true;
|
||||
that.form.validateFields([ 'username', 'password','inputCode', 'rememberMe' ], { force: true }, (err, values) => {
|
||||
if (!err) {
|
||||
loginParams.username = values.username
|
||||
loginParams.password = values.password
|
||||
|
||||
loginParams.remember_me = values.rememberMe
|
||||
loginParams.captcha = that.inputCodeContent
|
||||
loginParams.checkKey = that.currdatetime
|
||||
// console.log("登录参数",loginParams)
|
||||
loginParams.rsaPublicKey = that.rsaPublicKey;
|
||||
// 新建JSEncrypt对象
|
||||
let encrypt = new JSEncrypt();
|
||||
encrypt.setPublicKey(loginParams.rsaPublicKey);
|
||||
// 公钥加密
|
||||
loginParams.username = encrypt.encrypt(values.username)
|
||||
loginParams.password = encrypt.encrypt(values.password)
|
||||
//登录
|
||||
that.Login(loginParams).then((res) => {
|
||||
//登录成功
|
||||
this.loginSuccess()
|
||||
}).catch((err) => {
|
||||
if (err.code === 500) {
|
||||
@@ -309,6 +319,14 @@
|
||||
}).catch(()=>{
|
||||
this.requestCodeSuccess=false
|
||||
})
|
||||
this.getPublicKey();
|
||||
},
|
||||
//获取RSA公钥
|
||||
getPublicKey(){
|
||||
// 获取公钥
|
||||
getRSAPublicKey().then(res => {
|
||||
this.rsaPublicKey = res.result
|
||||
})
|
||||
},
|
||||
loginSuccess () {
|
||||
this.$router.push({ path: "/dashboard/analysis" }).catch((res)=>{})
|
||||
|
||||
Reference in New Issue
Block a user