parent
637739459e
commit
306600c73a
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class RsaKey {
|
||||
|
||||
//公钥
|
||||
private String publicKey;
|
||||
|
||||
//私钥
|
||||
private String privateKey;
|
||||
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
public class RsaUtil {
|
||||
|
||||
public static final String CHARSET = "UTF-8";
|
||||
public static final String RSA_ALGORITHM = "RSA";
|
||||
|
||||
|
||||
/**
|
||||
* 创建RSA 公钥-私钥
|
||||
*/
|
||||
public static RsaKey createKeys() throws NoSuchAlgorithmException {
|
||||
return createKeys(1024);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建RSA 公钥-私钥
|
||||
*/
|
||||
public static RsaKey createKeys(int keySize) throws NoSuchAlgorithmException {
|
||||
//为RSA算法创建一个KeyPairGenerator对象
|
||||
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
|
||||
|
||||
//初始化KeyPairGenerator对象,密钥长度
|
||||
kpg.initialize(keySize);
|
||||
//生成密匙对
|
||||
KeyPair keyPair = kpg.generateKeyPair();
|
||||
|
||||
//得到公钥
|
||||
Key publicKey = keyPair.getPublic();
|
||||
|
||||
String publicKeyStr = new String(Base64.encodeBase64(publicKey.getEncoded()));
|
||||
|
||||
//得到私钥
|
||||
Key privateKey = keyPair.getPrivate();
|
||||
String privateKeyStr = new String(Base64.encodeBase64(privateKey.getEncoded()));
|
||||
|
||||
RsaKey rsaKey = new RsaKey();
|
||||
rsaKey.setPublicKey(publicKeyStr);
|
||||
rsaKey.setPrivateKey(privateKeyStr);
|
||||
|
||||
return rsaKey;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 公钥加密
|
||||
*
|
||||
* @param originalText 原文
|
||||
* @param publicKey 公钥
|
||||
*/
|
||||
public static String publicEncrypt(String originalText, String publicKey) throws NoSuchAlgorithmException {
|
||||
RSAPublicKey rsaPublicKey = getPublicKey(publicKey);
|
||||
return publicEncrypt(originalText, rsaPublicKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公钥解密
|
||||
*
|
||||
* @param cipherText 密文
|
||||
* @param publicKey 公钥
|
||||
*/
|
||||
public static String publicDecrypt(String cipherText, String publicKey) throws NoSuchAlgorithmException {
|
||||
RSAPublicKey rsaPublicKey = getPublicKey(publicKey);
|
||||
return publicDecrypt(cipherText, rsaPublicKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥加密
|
||||
*
|
||||
* @param originalText 原文
|
||||
* @param privateKey 私钥
|
||||
*/
|
||||
public static String privateEncrypt(String originalText, String privateKey) throws NoSuchAlgorithmException {
|
||||
RSAPrivateKey rsaPrivateKey = getPrivateKey(privateKey);
|
||||
return privateEncrypt(originalText, rsaPrivateKey);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*
|
||||
* @param cipherText 密文
|
||||
* @param privateKey 私钥
|
||||
*/
|
||||
public static String privateDecrypt(String cipherText, String privateKey) throws NoSuchAlgorithmException {
|
||||
RSAPrivateKey rsaPrivateKey = getPrivateKey(privateKey);
|
||||
return privateDecrypt(cipherText, rsaPrivateKey);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 得到公钥
|
||||
*
|
||||
* @param publicKey 密钥字符串(经过base64编码)
|
||||
*/
|
||||
private static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException {
|
||||
//通过X509编码的Key指令获得公钥对象
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
|
||||
|
||||
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
|
||||
RSAPublicKey key = null;
|
||||
try {
|
||||
key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
|
||||
} catch (InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公钥加密
|
||||
*
|
||||
* @param originalText 原文
|
||||
* @param publicKey 公钥
|
||||
*/
|
||||
private static String publicEncrypt(String originalText, RSAPublicKey publicKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, originalText.getBytes(CHARSET), publicKey.getModulus().bitLength()));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("加密字符串[" + originalText + "]时遇到异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到私钥
|
||||
*
|
||||
* @param privateKey 密钥字符串(经过base64编码)
|
||||
*/
|
||||
private static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException {
|
||||
//通过PKCS#8编码的Key指令获得私钥对象
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
|
||||
|
||||
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
|
||||
RSAPrivateKey key = null;
|
||||
try {
|
||||
key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
|
||||
} catch (InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*
|
||||
* @param cipherText 密文
|
||||
* @param privateKey 私钥
|
||||
*/
|
||||
|
||||
private static String privateDecrypt(String cipherText, RSAPrivateKey privateKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(cipherText), privateKey.getModulus().bitLength()), CHARSET);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("解密字符串[" + cipherText + "]时遇到异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String privateEncrypt(String originalText, RSAPrivateKey privateKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
|
||||
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, originalText.getBytes(CHARSET), privateKey.getModulus().bitLength()));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("加密字符串[" + originalText + "]时遇到异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String publicDecrypt(String cipherText, RSAPublicKey publicKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, publicKey);
|
||||
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(cipherText), publicKey.getModulus().bitLength()), CHARSET);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("解密字符串[" + cipherText + "]时遇到异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
|
||||
int maxBlock;
|
||||
if (opmode == Cipher.DECRYPT_MODE) {
|
||||
maxBlock = keySize / 8;
|
||||
} else {
|
||||
maxBlock = keySize / 8 - 11;
|
||||
}
|
||||
int offSet = 0;
|
||||
byte[] buff;
|
||||
int i = 0;
|
||||
try (
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream()
|
||||
) {
|
||||
while (datas.length > offSet) {
|
||||
if (datas.length - offSet > maxBlock) {
|
||||
buff = cipher.doFinal(datas, offSet, maxBlock);
|
||||
} else {
|
||||
buff = cipher.doFinal(datas, offSet, datas.length - offSet);
|
||||
}
|
||||
out.write(buff, 0, buff.length);
|
||||
i++;
|
||||
offSet = i * maxBlock;
|
||||
}
|
||||
return out.toByteArray();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.config;
|
||||
|
||||
import io.metersphere.commons.utils.RsaKey;
|
||||
import io.metersphere.commons.utils.RsaUtil;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
@Configuration
|
||||
public class RsaConfig {
|
||||
@Bean
|
||||
public RsaKey rsaKey() throws NoSuchAlgorithmException {
|
||||
return RsaUtil.createKeys();
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ package io.metersphere.controller;
|
|||
|
||||
import io.metersphere.commons.constants.UserSource;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.RsaKey;
|
||||
import io.metersphere.commons.utils.RsaUtil;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.controller.request.LoginRequest;
|
||||
import io.metersphere.service.BaseDisplayService;
|
||||
|
@ -23,6 +25,8 @@ public class LoginController {
|
|||
private UserService userService;
|
||||
@Resource
|
||||
private BaseDisplayService baseDisplayService;
|
||||
@Resource
|
||||
private RsaKey rsaKey;
|
||||
|
||||
@GetMapping(value = "/isLogin")
|
||||
public ResultHolder isLogin() {
|
||||
|
@ -33,7 +37,7 @@ public class LoginController {
|
|||
}
|
||||
return ResultHolder.success(user);
|
||||
}
|
||||
return ResultHolder.error("");
|
||||
return ResultHolder.error(rsaKey.getPublicKey());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/signin")
|
||||
|
|
|
@ -1,12 +1,36 @@
|
|||
package io.metersphere.controller.request;
|
||||
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.RsaKey;
|
||||
import io.metersphere.commons.utils.RsaUtil;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class LoginRequest {
|
||||
private String username;
|
||||
private String password;
|
||||
private String authenticate;
|
||||
|
||||
|
||||
public String getUsername() {
|
||||
try {
|
||||
RsaKey rsaKey = CommonBeanFactory.getBean(RsaKey.class);
|
||||
return RsaUtil.privateDecrypt(username, rsaKey.getPrivateKey());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return username;
|
||||
}
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
try {
|
||||
RsaKey rsaKey = CommonBeanFactory.getBean(RsaKey.class);
|
||||
return RsaUtil.privateDecrypt(password, rsaKey.getPrivateKey());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return password;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,8 @@
|
|||
"xml-js": "^1.6.11",
|
||||
"yan-progress": "^1.0.3",
|
||||
"jsonpath": "^1.1.0",
|
||||
"vue-minder-editor-plus": "^1.0.14"
|
||||
"vue-minder-editor-plus": "^1.0.14",
|
||||
"jsencrypt": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.1.0",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import {
|
||||
COUNT_NUMBER, COUNT_NUMBER_SHALLOW,
|
||||
LicenseKey, ORIGIN_COLOR, ORIGIN_COLOR_SHALLOW,
|
||||
COUNT_NUMBER,
|
||||
COUNT_NUMBER_SHALLOW,
|
||||
LicenseKey,
|
||||
ORIGIN_COLOR,
|
||||
ORIGIN_COLOR_SHALLOW,
|
||||
PROJECT_ID,
|
||||
REFRESH_SESSION_USER_URL,
|
||||
ROLE_ADMIN,
|
||||
|
@ -12,6 +15,7 @@ import {
|
|||
} from "./constants";
|
||||
import axios from "axios";
|
||||
import {jsPDF} from "jspdf";
|
||||
import JSEncrypt from 'jsencrypt';
|
||||
|
||||
export function hasRole(role) {
|
||||
let user = getCurrentUser();
|
||||
|
@ -364,3 +368,11 @@ export function setColor(a, b, c, d) {
|
|||
export function setOriginColor() {
|
||||
setColor(ORIGIN_COLOR, ORIGIN_COLOR_SHALLOW, COUNT_NUMBER, COUNT_NUMBER_SHALLOW);
|
||||
}
|
||||
|
||||
export function publicKeyEncrypt(input, publicKey) {
|
||||
|
||||
let jsencrypt = new JSEncrypt({default_key_size: 1024});
|
||||
jsencrypt.setPublicKey(publicKey);
|
||||
|
||||
return jsencrypt.encrypt(input);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {saveLocalStorage} from '@/common/js/utils';
|
||||
import {publicKeyEncrypt, saveLocalStorage} from '@/common/js/utils';
|
||||
import {DEFAULT_LANGUAGE} from "@/common/js/constants";
|
||||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
|
@ -103,6 +103,8 @@ export default {
|
|||
|
||||
if (!response.data.success) {
|
||||
this.ready = true;
|
||||
// 保存公钥
|
||||
localStorage.setItem("publicKey", response.data.message);
|
||||
} else {
|
||||
let user = response.data.data;
|
||||
saveLocalStorage(response.data);
|
||||
|
@ -159,7 +161,15 @@ export default {
|
|||
});
|
||||
},
|
||||
doLogin() {
|
||||
this.result = this.$post(this.loginUrl, this.form, response => {
|
||||
let publicKey = localStorage.getItem("publicKey");
|
||||
|
||||
let form = {
|
||||
username: publicKeyEncrypt(this.form.username, publicKey),
|
||||
password: publicKeyEncrypt(this.form.password, publicKey),
|
||||
authenticate: this.form.authenticate
|
||||
};
|
||||
|
||||
this.result = this.$post(this.loginUrl, form, response => {
|
||||
saveLocalStorage(response);
|
||||
sessionStorage.setItem('loginSuccess', 'true');
|
||||
this.getLanguage(response.data.language);
|
||||
|
|
Loading…
Reference in New Issue