在SpringBoot+VUE中 实现登录-RSA的加密解密

步骤-先理清楚在动手

  1. 前端首先调用后端的公钥接口,
  2. 在前端加密密码传输至后端登录接口
  3. 后端用私钥解密码
  4. 拿着用户名去数据库查询出来的盐值加密的 密码1
  5. 用私钥解密密码登录密码加盐值得到 密码2
  6. 比较密码1与密码2,相同则登录成功,跳转首页|其他页面
前端实现
  1. 如果当前vue项目没有安装 jsencrypt 你需要先使用 npm 来安装 jsencrypt。

使用 npm:

npm install jsencrypt --save

  1. 调用后端接口获取公钥。
 created() {this.getPublicKey();},methods: {async getPublicKey() {try {// 此处为调用后端接口。const response = await getPublicKey();if (response.data.code === 200) {this.publicKey = response.data.data;}}catch (error) {Message.error(error.message);}}}
  1. 根据获取到的公钥和 jsencrypt 加密用户输入的密码
import JSEncrypt from 'jsencrypt';// 提交表单-此处只处理了密码信息,后续的接口和 token以及页面跳转均未处理
async handleSubmit() {// 验证if (!this.password) {Message.error('请输入密码!');return;}// 加密const crypt = new JSEncrypt();crypt.setPublicKey(this.publicKey);// 得到加密后的密码const encrypted = crypt.encrypt(this.password);// 无感跳转页面 // this.$router.push({path: '/Index'});}

此时就可以向后端发送登录请求了。

后端实现
  1. 工具类
import java.util.Base64;public class Base64Util {public static byte[] encode(byte[] signData) {return Base64.getEncoder().encode(signData);}public static byte[] decode(String signData) {return Base64.getDecoder().decode(signData);}public static String encodeToStr(byte[] signData) {return new String(Base64.getEncoder().encode(signData));}public static String decodeToStr(String signData) {return new String(Base64.getDecoder().decode(signData));}
}

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;/*** Java加密解密工具.3DES SHA1 MD5 BASE64编码 AES加密** @author 党泽坤*/
public class EncryptUtil {// 密钥private final static String secretKey = "dzkandzhj202410$#365#001";// 向量private final static String iv = "01234567";// 加解密统一使用的编码方式private final static String encoding = "utf-8";// 无需创建对象private EncryptUtil() {}/*** SHA1加密Bit数据** @param source byte数组* @return 加密后的byte数组*/public static byte[] SHA1Bit(byte[] source) {try {MessageDigest sha1Digest = MessageDigest.getInstance("SHA-1");sha1Digest.update(source);byte targetDigest[] = sha1Digest.digest();return targetDigest;} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}}/*** SHA1加密字符串数据** @param source 要加密的字符串* @return 加密后的字符串*/public static String SHA1(String source) {return byte2HexStr(SHA1Bit(source.getBytes()));}/*** MD5加密Bit数据** @param source byte数组* @return 加密后的byte数组*/public static byte[] MD5Bit(byte[] source) {try {// 获得MD5摘要算法的 MessageDigest对象MessageDigest md5Digest = MessageDigest.getInstance("MD5");// 使用指定的字节更新摘要md5Digest.update(source);// 获得密文return md5Digest.digest();} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}}/*** MD5加密字符串,32位长** @param source 要加密的内容* @return 加密后的内容*/public static String MD5(String source) {return byte2HexStr(MD5Bit(source.getBytes()));}/*** BASE64编码** @param source 要编码的字符串* @return 编码过的字符串* @throws UnsupportedEncodingException*/public static String encodeBASE64(String source) throws UnsupportedEncodingException {return Base64.getEncoder().encodeToString(source.getBytes(encoding));}/*** BASE64解码** @param encodeSource 编码过的字符串* @return 编码前的字符串* @throws UnsupportedEncodingException*/public static String decodeBASE64(String encodeSource) throws UnsupportedEncodingException {return new String(Base64.getDecoder().decode(encodeSource), encoding);}/*** AES加密** @param content  待加密的内容* @param password 加密密码* @return*/public static byte[] encryptBitAES(byte[] content, String password) {try {Cipher encryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器encryptCipher.init(Cipher.ENCRYPT_MODE, getKey(password));// 初始化byte[] result = encryptCipher.doFinal(content);return result; // 加密} catch (Exception e) {throw new RuntimeException(e);}// return null;}/*** AES解密** @param content  待解密内容* @param password 解密密钥* @return*/public static byte[] decryptBitAES(byte[] content, String password) {try {Cipher decryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器decryptCipher.init(Cipher.DECRYPT_MODE, getKey(password));// 初始化return decryptCipher.doFinal(content); // 加密结果} catch (Exception e) {throw new RuntimeException(e);}// return null;}/*** AES字符串加密** @param content  待加密的内容* @param password 加密密码* @return*/public static String encryptAES(String content, String password) {return byte2HexStr(encryptBitAES(content.getBytes(), password));}/*** AES字符串解密** @param content  待解密内容* @param password 解密密钥* @return*/public static String decryptAES(String content, String password) {return new String(decryptBitAES(hexStr2Bytes(content), password));}/*** 从指定字符串生成密钥** @param password 构成该秘钥的字符串* @return 生成的密钥* @throws NoSuchAlgorithmException*/private static Key getKey(String password) throws NoSuchAlgorithmException {SecureRandom secureRandom = new SecureRandom(password.getBytes());// 生成KEYKeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128, secureRandom);SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();// 转换KEYSecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");return key;}/*** 将byte数组转换为表示16进制值的字符串. 如:byte[]{8,18}转换为:0812 和 byte[]* hexStr2Bytes(String strIn) 互为可逆的转换过程.** @param bytes 需要转换的byte数组* @return 转换后的字符串*/public static String byte2HexStr(byte[] bytes) {int bytesLen = bytes.length;// 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍StringBuffer hexString = new StringBuffer(bytesLen * 2);for (int i = 0; i < bytesLen; i++) {// 将每个字节与0xFF进行与运算,然后转化为10进制,然后借助于Integer再转化为16进制String hex = Integer.toHexString(bytes[i] & 0xFF);if (hex.length() < 2) {hexString.append(0);// 如果为1位 前面补个0}hexString.append(hex);}return hexString.toString();}/*** 将表示16进制值的字符串转换为byte数组, 和 String byte2HexStr(byte[] bytes) 互为可逆的转换过程.** @param strIn* @return 转换后的byte数组*/public static byte[] hexStr2Bytes(String strIn) {byte[] arrB = strIn.getBytes();int iLen = arrB.length;// 两个字符表示一个字节,所以字节数组长度是字符串长度除以2byte[] arrOut = new byte[iLen / 2];for (int i = 0; i < iLen; i = i + 2) {String strTmp = new String(arrB, i, 2);arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);}return arrOut;}/*** 3DES加密** @param plainText 普通文本* @return* @throws Exception*/public static String d3esEncode(String plainText) {Key deskey = null;byte[] encryptData = null;try {DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");deskey = keyfactory.generateSecret(spec);Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");IvParameterSpec ips = new IvParameterSpec(iv.getBytes());cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);encryptData = cipher.doFinal(plainText.getBytes(encoding));} catch (Exception e) {e.printStackTrace();}return Base64.getEncoder().encodeToString(encryptData);}/*** 3DES解密** @param encryptText 加密文本* @return* @throws Exception*/public static String d3esDecode(String encryptText) {Key deskey = null;byte[] decryptData = null;String result = "";if (null != encryptText && !"".equals(encryptText)) {try {DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");deskey = keyfactory.generateSecret(spec);Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");IvParameterSpec ips = new IvParameterSpec(iv.getBytes());cipher.init(Cipher.DECRYPT_MODE, deskey, ips);decryptData = cipher.doFinal(Base64.getDecoder().decode(encryptText));result = new String(decryptData, encoding);} catch (Exception e) {e.printStackTrace();}}return result;}public static void main(String[] args) {// 此处测试}
}

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
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;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;/*** <p>* RSA公钥/私钥/签名工具包* </p>* <p>* 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)* </p>* <p>* 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>* 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>* 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全* </p>** @author IceWee* @version 1.0* @date 2012-4-26*/
public class RSAUtils {/*** 加密算法RSA*/public static final String KEY_ALGORITHM = "RSA";/*** 签名算法*/public static final String SIGNATURE_ALGORITHM = "MD5withRSA";/*** 获取公钥的key*/private static final String PUBLIC_KEY = "RSAPublicKey";/*** 获取私钥的key*/private static final String PRIVATE_KEY = "RSAPrivateKey";/*** RSA最大加密明文大小*/private static final int MAX_ENCRYPT_BLOCK = 64;/*** RSA最大解密密文大小*/private static final int MAX_DECRYPT_BLOCK = 128;/*** 加密算法RSA/ECB/PKCS1Padding和填充模式*/private static final String ALGORITHM = "PBKDF2WithHmacSHA256";/*** 迭代次数*/private static final int ITERATIONS = 65536;/*** 密钥长度*/private static final int KEY_LENGTH = 256;/*** 盐长度 (字节长度)*/private static final int SALT_LENGTH = 16;/*** <p>* 生成密钥对(公钥和私钥)* </p>** @return* @throws Exception*/public static Map<String, Object> genKeyPair() {KeyPairGenerator keyPairGen = null;try {keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGen.initialize(1024);KeyPair keyPair = keyPairGen.generateKeyPair();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();Map<String, Object> keyMap = new HashMap<String, Object>(2);keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}}/*** <p>* 获取私钥* </p>** @param keyMap 密钥对* @return* @throws Exception*/public static String getPrivateKey(Map<String, Object> keyMap) {Key key = (Key) keyMap.get(PRIVATE_KEY);return Base64Util.encodeToStr(key.getEncoded());}/*** <p>* 获取公钥* </p>** @param keyMap 密钥对* @return* @throws Exception*/public static String getPublicKey(Map<String, Object> keyMap) {Key key = (Key) keyMap.get(PUBLIC_KEY);return Base64Util.encodeToStr(key.getEncoded());}/*** <p>* 用私钥对信息生成数字签名* </p>** @param data       已加密数据* @param privateKey 私钥(BASE64编码)* @return* @throws Exception*/public static String sign(byte[] data, String privateKey) throws Exception {byte[] keyBytes = Base64Util.decode(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initSign(privateK);signature.update(data);return Base64Util.encodeToStr(signature.sign());}/*** <p>* 校验数字签名* </p>** @param data      已加密数据* @param publicKey 公钥(BASE64编码)* @param sign      数字签名* @return* @throws Exception*/public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {byte[] keyBytes = Base64Util.decode(publicKey);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);PublicKey publicK = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initVerify(publicK);signature.update(data);return signature.verify(Base64Util.decode(sign));}/*** <P>* 私钥解密* </p>** @param encryptedData 已加密数据* @param privateKey    私钥(BASE64编码)* @return* @throws Exception*/public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {byte[] keyBytes = Base64Util.decode(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateK);int inputLen = encryptedData.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段解密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();return decryptedData;}/*** <p>* 公钥解密* </p>** @param encryptedData 已加密数据* @param publicKey     公钥(BASE64编码)* @return* @throws Exception*/public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception {byte[] keyBytes = Base64Util.decode(publicKey);X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicK = keyFactory.generatePublic(x509KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicK);int inputLen = encryptedData.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段解密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();return decryptedData;}/*** <p>* 公钥加密* </p>** @param data      源数据* @param publicKey 公钥(BASE64编码)* @return* @throws Exception*/public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {byte[] keyBytes = Base64Util.decode(publicKey);X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicK = keyFactory.generatePublic(x509KeySpec);// 对数据加密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicK);int inputLen = data.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段加密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();return encryptedData;}/*** <p>* 私钥加密* </p>** @param data       源数据* @param privateKey 私钥(BASE64编码)* @return* @throws Exception*/public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {byte[] keyBytes = Base64Util.decode(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateK);int inputLen = data.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段加密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();return encryptedData;}/*** java端公钥加密*/public static String encryptedDataOnJava(String data, String publicKey) {try {data = Base64Util.encodeToStr(encryptByPublicKey(data.getBytes(), publicKey));} catch (Exception e) {e.printStackTrace();}return data;}/*** java端私钥解密*/public static String decryptDataOnJava(String data, String privateKey) {String temp = "";try {byte[] rs = Base64Util.decode(data);// 解密 以utf-8的方式生成字符串temp = new String(RSAUtils.decryptByPrivateKey(rs, privateKey), StandardCharsets.UTF_8);} catch (Exception e) {e.printStackTrace();}return temp;}public static void main(String[] args) {try {Map<String, Object> keyMap = RSAUtils.genKeyPair();String publicKey = RSAUtils.getPublicKey(keyMap);String privateKey = RSAUtils.getPrivateKey(keyMap);System.out.println("publicKey = " + publicKey);System.out.println("privateKey = " + privateKey);System.out.println("=============================");String s = encryptedDataOnJava("123456", publicKey);System.out.println("java端公钥加密  " + s);String s21 = decryptDataOnJava(s, privateKey);System.out.println("java端私钥解密 = " + s21);//byte[] bytes = generateSalt();//System.out.println("生成的盐 = " + bytes);String s1 = "9be08179ba82f8e2068928c2494b577c";System.out.println("16制字符 = " + s1.length());byte[] bytes1 = hexToBytes(s1);//System.out.println("bytesToHex(bytes) = " + Arrays.equals(bytes, bytes1));String ss = hashPassword("123456", bytes1);System.out.println("生成的哈希值 = " + ss.equals("zDuIyDjB1Qwi54j2j2fyPsmkvAjUNw/rT/92pAG6fNg="));} catch (Exception e) {e.printStackTrace();}}/*** =============================== 密码加盐 =======================*//*** 生成随机盐** @return* @throws NoSuchAlgorithmException*/public static byte[] generateSalt() {try {   // 使用 SecureRandom 来生成高质量的随机数SecureRandom sr  = SecureRandom.getInstanceStrong();byte[] salt = new byte[SALT_LENGTH];sr.nextBytes(salt);return salt;} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}}/*** 将字节数组转换为十六进制字符串** @param bytes* @return*/public static String bytesToHex(byte[] bytes) {StringBuilder sb = new StringBuilder();for (byte b : bytes) {sb.append(String.format("%02x", b));}return sb.toString();}/*** 将十六进制字符串转换为字节数组** @param hex* @return byte[]*/public static byte[] hexToBytes(String hex) {int len = hex.length();byte[] data = new byte[len / 2];for (int i = 0; i < len; i += 2) {data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)+ Character.digit(hex.charAt(i + 1), 16));}return data;}/*** ================================ 密码加密 ================================*//*** 根据盐和密码生成加密密码(哈希值)** @param password 密码* @param salt     盐* @return 哈希值(Base64编码)* @throws NoSuchAlgorithmException* @throws InvalidKeySpecException*/public static String hashPassword(String password, byte[] salt) {try {// 创建PBEKeySpec对象PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS, KEY_LENGTH);// 创建SecretKeyFactory对象SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);// 生成密钥byte[] hash = factory.generateSecret(spec).getEncoded();// 使用Base64编码return Base64.getEncoder().encodeToString(hash);} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {throw new RuntimeException(e);}}/*** 校验密码是否匹配* @param dbHashPassword     数据库中存储的密码* @param inputPassword     用户输入的密码* @param dbSalt     数据库中存储的盐* @return  true 匹配成功 false 匹配失败*/public static boolean hashPasswordIsMatch(String dbHashPassword, String inputPassword, String dbSalt) {byte[] byteSalts = hexToBytes(dbSalt);String newHashedPassword = hashPassword(inputPassword, byteSalts);return dbHashPassword.equals(newHashedPassword);}}
  1. Controller 实现。
	/*** 获取公钥** @param request   HttpServletRequest对象* @return*/@ApiOperation(value = "登陆,获取公钥", httpMethod = "GET")@GetMapping("/publicKey")public String publicKey(HttpServletRequest request) {return generateKey(request);}/*** 生成随机码* @param request HttpServletRequest对象*/private String generateKey(HttpServletRequest request) {Map<String, Object> keyMap = RSAUtils.genKeyPair();String publicKey = RSAUtils.getPublicKey(keyMap);String privateKey = RSAUtils.getPrivateKey(keyMap);request.getSession().setAttribute("privateKey", privateKey);return StringUtils.isBlank(publicKey) ? "" : publicKey;}/*** 登录* 此处简化,根据自己业务自定* @param request     HttpServletRequest对象* @param loginRequest       登录请求体*/@ApiOperation(value = "登录", httpMethod = "POST")@PostMapping(value = "/login")public void secondLoginCostDashboard(HttpServletRequest request, @RequestBody LoginRequest loginRequest) {String privateKey = (String) request.getSession().getAttribute("privateKey");Validator.validateFalse(StringUtils.isBlank(privateKey), "鉴权失败,请刷新页面,重试!");String account = loginRequest.getUserAccount();// 获取登录人信息SysUser sysUser = userExist(account);String inputPassword = loginRequest.getPassword();// 密码解密String decryptPassword = RSAUtils.decryptDataOnJava(inputPassword, privateKey);// 输入和db存入的密码对比, 盐boolean isMatch = RSAUtils.hashPasswordIsMatch(sysUser.getPassword(), decryptPassword, sysUser.getSalt());Validator.validateTrue(isMatch,"密码输入错误,请检查!")  ;}/*** 重设密码* @param request     HttpServletRequest对象* @param loginRequest       登录请求体*/@ApiOperation(value = "重设密码", httpMethod = "POST")@PostMapping(value = "/restPassword")public void updatePasswordCostDashboard(HttpServletRequest request, @RequestBody LoginRequest loginRequest) {String privateKey = (String) request.getSession().getAttribute("privateKey");Validator.validateFalse(StringUtils.isBlank(privateKey), "鉴权失败,请刷新页面,重试!");String account = loginRequest.getUserAccount();SysUser sysUser = userExist(account);// 原密码String oldPwd = loginRequest.getPassword();String oldDecryptPwd = RSAUtils.decryptDataOnJava(oldPwd, privateKey);boolean isMatch = RSAUtils.hashPasswordIsMatch(sysUser.getPassword(), oldDecryptPwd, sysUser.getSalt());Validator.validateTrue(isMatch,"原密码输入错误,请检查!")  ;// 新密码String newPwd = loginRequest.getNewPassword();// 解密后的新密码String newDecryptPwd = RSAUtils.decryptDataOnJava(newPwd, privateKey);// 生成盐byte[] saltBytes = RSAUtils.generateSalt();String saltStr = RSAUtils.bytesToHex(saltBytes);// 加盐后的密码String newHashPassword =  RSAUtils.hashPassword(newDecryptPwd, saltBytes);sysUser.setPassword(newHashPassword);sysUser.setSalt(saltStr);// 调用更新接口}

请求实体Vo

public class LoginRequest {/*** 登录账号*/private String userAccount ;/*** 密码*/private String password;/*** 公钥*/private String publicKey;/*** 新密码*/private String newPassword;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/56583.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型(LLM)应用开发平台

AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型&#xff08;LLM&#xff09;应用开发平台 目录 AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型&#xff08;LLM&#xff09;应用开发平台 一、简单介绍 二、Docker 下载安…

设置 Notepad++ 制表符(Tab 缩进)宽度为2个空格大小

Notepad 默认的制表符宽度是 4 个空格的大小&#xff0c;一个规模比较大的代码段或者 xml 等文件&#xff0c;小屏幕打开时看到的情景真的和让人着急&#xff0c;拖来拖去&#xff01;有两种方案可以解决这种情况。 修改缩进为空格 这种我们不太推荐&#xff0c;但是有些公司…

小白必看web专题!配置环境还在用phpstudy?该用docker了!(php+nginx+mysql+phpmyadmin。)

大家好&#xff0c;我是Dest1ny。 大家用mac或者是windows都是使用phpstudy。 今天docker来搭建一整个phpnginxmysqlphpmyadmin。 而且mac用docker比较方便&#xff01; docker才是众望所归。 大家多多点赞&#xff0c;多多支持&#xff0c;谢谢&#xff01;&#xff01;&…

Qml-Item的构造和显示顺序

Qml-Item的构造和显示顺序 qml文件中组件构造顺序 在同一个qml文件中&#xff0c;同层级的Item, 文件尾的Item优先构造&#xff0c;文件首的Item后构造。这就能解释默认情况下同一个qml文件中&#xff0c;几个同层级的item都设置了focus:true&#xff0c;为啥最上面item最终有…

echarts设置x轴中文垂直显示,x轴滚动条

echarts官网配置&#xff0c;主要配置dataZoom option {xAxis: {type: category,data: [张三,李四,王五,赵六,孙七,周八,吴九,郑十,钱十一,陈十二,刘十三,杨十四,黄十五,何十六,宋十七],axisLabel: {formatter: function (value) {return value.split().join(\n); // 使用换行…

超全!一文详解大型语言模型的11种微调方法

导读&#xff1a;大型预训练模型是一种在大规模语料库上预先训练的深度学习模型&#xff0c;它们可以通过在大量无标注数据上进行训练来学习通用语言表示&#xff0c;并在各种下游任务中进行微调和迁移。随着模型参数规模的扩大&#xff0c;微调和推理阶段的资源消耗也在增加。…

爬虫实战(黑马论坛)

1.定位爬取位置内容&#xff1a; # -*- coding: utf-8 -*- import requests import time import re# 请求的 URL 和头信息 url https://bbs.itheima.com/forum-425-1.html headers {user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like…

基于Java实现(PC)大学班级事务管理系统

courseDesign_Java Java 课设 要求 本次设计要求利用 Java 实现 C/S 模式的大学班级内日常事务管理系统&#xff08;PC 版&#xff0c;应用于校内网有线网络访问&#xff0c;暂不开发移动端&#xff09;&#xff0c;不得依赖现有的建模框架&#xff0c;使用 swings 技术完成如…

华为OD机试 - 爱吃蟠桃的孙悟空 - 二分查找(Python/JS/C/C++ 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

决策树和集成学习的概念以及部分推导

一、决策树 1、概述 决策树是一种树形结构&#xff0c;树中每个内部节点表示一个特征上的判断&#xff0c;每个分支代表一个判断结果的输出&#xff0c;每个叶子节点代表一种分类结果 决策树的建立过程&#xff1a; 特征选择&#xff1a;选择有较强分类能力的特征决策树生成…

闯关leetcode——110. Balanced Binary Tree

大纲 题目地址内容 解题代码地址 题目 地址 https://leetcode.com/problems/balanced-binary-tree/description/ 内容 Given a binary tree, determine if it is height-balanced. A height-balanced binary tree is a binary tree in which the depth of the two subtrees…

决策树算法新手入门:从基础理论到Python实现

决策树新手入门详细教程 一、数学基础1. 信息熵(1) 基本定义(2) 条件熵(3) 有关定律 2. 信息增益 二、决策树的组成1. 决策节点2. 叶子节点3. 决策树的深度 三、决策树的建立&#xff08;基于信息增益&#xff09;—— ID31. 计算根节点的信息熵2. 计算属性的信息增益(1) 职业(…

【升华】python基础包NumPy学习

NumPy是使用Python进行科学计算的基础软件包。除其他外&#xff0c;它包括&#xff1a; 功能强大的N维数组对象。精密广播功能函数。集成 C/C和Fortran 代码的工具。强大的线性代数、傅立叶变换和随机数功能。 # 1、安装包 $ pip install numpy# 2、进入python的交互式界面 $…

蓄电池在线监测:保障电力安全的智能之选---安科瑞 吴雅芳

一、蓄电池在线监测的重要性 随着科技的飞速发展&#xff0c;蓄电池在各个领域的应用日益广泛&#xff0c;从通信、电力到金融、医疗等行业&#xff0c;蓄电池都扮演着至关重要的角色。然而&#xff0c;蓄电池在使用过程中也面临着诸多问题。 蓄电池老化可能导致鼓胀、短路、漏…

React 子组件调用父组件的方法,以及互相传递数据

<script type"text/babel" data-type"module"> import React, { StrictMode, useState } from react; import { createRoot } from react-dom/client;const ParentComponent () > {const [message, setMessage] useState("")//父组件…

【火山引擎】 Chat实践 | 大模型调用实践 | python

目录 一 前期工作 二 Doubao-pro-4k_test实践 一 前期工作 1 已在火山方舟控制台在线推理页面创建了推理接入点 ,接入大语言模型并获取接入点 ID。 2 已参考安装与初始化中的步骤完成 SDK 安装和访问凭证配置

基于SSM的个性化商铺系统【附源码】

基于SSM的个性化商铺系统 效果如下&#xff1a; 用户登录界面 app首页界面 商品信息界面 店铺信息界面 用户功能界面 我的订单界面 后台登录界面 管理员功能界面 用户管理界面 商家管理界面 店铺信息管理界面 商家功能界面 个人中心界面 研究背景 研究背景 科学技术日新月异…

LeetCode-3191 使二进制数组全部等于1的最少操作次数

又来到了今天的每日一题&#xff0c;距离上次更新每日一题得有十天了。 主要原因是这十天的题要么简单到爆&#xff0c;要么难到爆&#xff0c;再要么就是最近学校安排实训&#xff0c;时间比较紧。 废话不多说&#xff0c;来看看今天的题目。 题目很简单&#xff0c;就是给个…

CTF(五)

导言&#xff1a; 本文主要讲述在CTF竞赛中&#xff0c;web类题目easyphp。 靶场链接&#xff1a;攻防世界 (xctf.org.cn) 参考文章原文链接&#xff1a;Web安全攻防世界05 easyphp&#xff08;江苏工匠杯&#xff09;_攻防世界 easyphp-CSDN博客 一&#xff0c;观察页面。…

校验台账生成网络事业调查表的方法

校验台账生成网络事业调查表的方法 一、打开教育事业统计调查表学校&#xff08;机构&#xff09;信息管理标准化台账“采集信息核查辅助工具二、导入本校台账并校验三、调查表统计导出四、完 一、打开教育事业统计调查表学校&#xff08;机构&#xff09;信息管理标准化台账“…