若依前后端分离项目-明文密码加密传输

若依版本:3.8.6

一,后端

1,新建工具类RSAUtils

package com.ruoyi.common.utils;

import org.apache.commons.codec.binary.Base64;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

@Component
public class RSAUtils {
    // Rsa 私钥 也可固定秘钥对 若依原写法(不安全)
    public static String privateKeys = "";
    private static String publicKeyStr = "";
    private static String privateKeyStr = "";
    private static final RSAKeyPair rsaKeyPair = new RSAKeyPair();

    /**
     * 私钥解密
     *
     * @param text 待解密的文本
     * @return 解密后的文本
     */
    public static String decryptByPrivateKey(String text) throws Exception {
        return decryptByPrivateKey(rsaKeyPair.getPrivateKey(), text);
    }

    /**
     * 公钥解密
     *
     * @param publicKeyString 公钥
     * @param text            待解密的信息
     * @return 解密后的文本
     */
    public static String decryptByPublicKey(String publicKeyString, String text) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
        return new String(result);
    }

    /**
     * 私钥加密
     *
     * @param privateKeyString 私钥
     * @param text             待加密的信息
     * @return 加密后的文本
     */
    public static String encryptByPrivateKey(String privateKeyString, String text) throws Exception {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(text.getBytes());
        return Base64.encodeBase64String(result);
    }

    /**
     * 私钥解密
     *
     * @param privateKeyString 私钥
     * @param text             待解密的文本
     * @return 解密后的文本
     */
    public static String decryptByPrivateKey(String privateKeyString, String text) throws Exception {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
        return new String(result);
    }

    /**
     * 公钥加密
     *
     * @param publicKeyString 公钥
     * @param text            待加密的文本
     * @return 加密后的文本
     */
    public static String encryptByPublicKey(String publicKeyString, String text) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(text.getBytes());
        return Base64.encodeBase64String(result);
    }

    /**
     * 构建RSA密钥对
     *
     * @return 生成后的公私钥信息
     */
    @Bean
    public void generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
        String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
        rsaKeyPair.setPrivateKey(privateKeyString);
        rsaKeyPair.setPublicKey(publicKeyString);
        publicKeyStr = publicKeyString;
        privateKeyStr = privateKeyString;
    }


    public static String getPublicKey() {
        return publicKeyStr;
    }

    public static String getPrivateKey() {
        return privateKeyStr;
    }

    public static RSAKeyPair rsaKeyPair() {
        return rsaKeyPair;
    }

    /**
     * RSA密钥对对象
     */
    public static class RSAKeyPair {
        private String publicKey;
        private String privateKey;

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

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

        public RSAKeyPair() {

        }

        public RSAKeyPair(String publicKey, String privateKey) {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }

        public String getPublicKey() {
            return publicKey;
        }

        public String getPrivateKey() {
            return privateKey;
        }
    }
}

2,添加getPublicKey的接口

SysLoginController

    /**
     * 获取公钥:前端用来密码加密
     * @return
     */
    @GetMapping("/getPublicKey")
    public RSAUtils.RSAKeyPair getPublicKey() {
        return RSAUtils.rsaKeyPair();
    }

3,添加白名单

SecurityConfig

.antMatchers("/getPublicKey").permitAll()

4,修改登录生成Token

SysLoginService

UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, RSAUtils.decryptByPrivateKey(password));

5,修改密码接口

SysProfileController

    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("/updatePwd")
    public AjaxResult updatePwd(String oldPassword, String newPassword) throws Exception {
        LoginUser loginUser = getLoginUser();
        String userName = loginUser.getUsername();
        String password = loginUser.getPassword();
        //解密
        oldPassword = RSAUtils.decryptByPrivateKey(oldPassword);
        newPassword = RSAUtils.decryptByPrivateKey(newPassword);
        if (!SecurityUtils.matchesPassword(oldPassword, password))
        {
            return error("修改密码失败,旧密码错误");
        }
        if (SecurityUtils.matchesPassword(newPassword, password))
        {
            return error("新密码不能与旧密码相同");
        }
        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
        {
            // 更新缓存用户密码
            loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改密码异常,请联系管理员");
    }

6,重置密码接口

SysUserController

    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user) throws Exception {
        // 解密
        String password = RSAUtils.decryptByPrivateKey(user.getPassword());
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(password));
        user.setUpdateBy(getUsername());
        return toAjax(userService.resetPwd(user));
    }

7,新建用户接口

SysUserController

    /**
     * 新增用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysUser user) throws Exception {
        // 解密
        user.setPassword(RSAUtils.decryptByPrivateKey(user.getPassword()));
        if (!userService.checkUserNameUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
        }
        user.setCreateBy(getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        return toAjax(userService.insertUser(user));
    }

8,注释密码长度校验

SysLoginService

        // 密码如果不在指定范围内 错误
//        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
//                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
//        {
//            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
//            throw new UserPasswordNotMatchException();
//        }

二,前端

1,修改加密方法

jsencrypt.js

import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'

// 密钥对生成 http://web.chacuo.net/netrsakeypair

// 这里注掉了原来固定的公私钥
const publicKey = ''
const privateKey = ''

// 加密
export function encrypt(txt, publicKey) {
  const encryptor = new JSEncrypt()
  encryptor.setPublicKey(publicKey) // 设置公钥
  return encryptor.encrypt(txt) // 对数据
}

// 解密(暂无使用)
export function decrypt(txt) {
  const encryptor = new JSEncrypt()
  encryptor.setPrivateKey(privateKey) // 设置私钥
  return encryptor.decrypt(txt) // 对数据进行解密
}

2,添加获取公钥的方法

login.js

// 获取公钥
export function getPublicKey() {
  return request({
    url: '/getPublicKey',
    method: 'get',
  })
}

3,修改登录方法

store/modules/user.js

  actions: {
    getPublicKey() {
      return new Promise((resolve, reject) => {
        getPublicKey()
          .then(res => {
            resolve(res)
          })
          .catch(error => {
            reject(error)
          })
      })
    },
    // 登录
    Login({ commit, dispatch }, userInfo) {
      return new Promise((resolve, reject) => {
        dispatch('getPublicKey').then(res => {
          let publicKey = res.publicKey
          const username = userInfo.username.trim()
          //调用加密方法(传密码和公钥)
          const password = encrypt(userInfo.password, publicKey)
          const code = userInfo.code
          const uuid = userInfo.uuid
          login(username, password, code, uuid)
            .then(res => {
              setToken(res.token)
              commit('SET_TOKEN', res.token)
              resolve()
            })
            .catch(error => {
              reject(error)
            })
        })
      })
    },

4,修改密码方法

views/sysytem/user/profile/resetPwd.vue

  methods: {
    getPublicKey() {
      return new Promise((resolve, reject) => {
        getPublicKey()
          .then(res => {
            resolve(res)
          })
          .catch(error => {
            reject(error)
          })
      })
    },
    submit() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          this.getPublicKey().then(res=>{
            let publicKey = res.publicKey
            const oldPassword = encrypt(this.user.oldPassword, publicKey)
            const newPassword = encrypt(this.user.newPassword, publicKey)
            updateUserPwd(oldPassword, newPassword).then(
              response => {
                this.$modal.msgSuccess("修改成功");
              }
            );
          })

        }
      });
    },
    close() {
      this.$tab.closePage();
    }
  }

5,重置密码方法

views/sysytem/user/index.vue

    getPublicKey() {
      return new Promise((resolve, reject) => {
        getPublicKey()
          .then(res => {
            resolve(res)
          })
          .catch(error => {
            reject(error)
          })
      })
    },
    /** 重置密码按钮操作 */
    handleResetPwd(row) {
      this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        closeOnClickModal: false,
        inputPattern: /^.{5,20}$/,
        inputErrorMessage: "用户密码长度必须介于 5 和 20 之间"
      }).then(({ value }) => {
          this.getPublicKey().then(res=> {
            let publicKey = res.publicKey
            const encryptValue = encrypt(value,publicKey)
            resetUserPwd(row.userId, encryptValue).then(response => {
              this.$modal.msgSuccess("修改成功,新密码是:" + value);
            });
          })

        }).catch(() => {});
    },

6,新建用户方法

views/sysytem/user/index.vue

    /** 提交按钮 */
    submitForm: function () {
      this.$refs["form"].validate((valid) => {
        if (valid) {
          if (this.form.userId != undefined) {
            this.form.deptId = this.form.deIds[0];
            this.form.deptIds = this.form.deIds.join(",");
            updateUser(this.form).then((response) => {
              this.$modal.msgSuccess("修改成功");
              this.open = false;
              this.getList();
            });
          } else {
            this.getPublicKey().then(res=> {
              let publicKey = res.publicKey
              this.form.password = encrypt(this.form.password,publicKey)
              this.form.deptId = this.form.deIds[0];
              this.form.deptIds = this.form.deIds.join(",");
              addUser(this.form).then((response) => {
                this.$modal.msgSuccess("新增成功");
                this.open = false;
                this.getList();
              });
            })
          }
        }
      });
    },

三,添加密码复杂度规则

1,新建用户

新建用户的时候密码为默认密码,只需要把默认密码设置成符合复杂度规则的密码即可。

2,修改密码

views/sysytem/user/profile/resetPwd.vue

passwordRegex :正则校验表达式

callback:校验不通过的提示信息

  data() {
    const equalToPassword = (rule, value, callback) => {
      if (this.user.newPassword !== value) {
        callback(new Error("两次输入的密码不一致"));
      } else {
        callback();
      }
    };
    const validateNewPassword = (rule, value, callback) =>  {
      const passwordRegex = /^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*()_+={}[\]|\\:;'",<>.?/-])[A-Za-z\d!@#$%^&*()_+={}[\]|\\:;'",<>.?/-]{6,}$/;
      if (!passwordRegex.test(value)) {
        callback(new Error("密码应至少6位且包含数字、大小写字母和特殊字符中的四种"));
      } else {
        callback();
      }
    }
    return {
      user: {
        oldPassword: undefined,
        newPassword: undefined,
        confirmPassword: undefined
      },
      // 表单校验
      rules: {
        oldPassword: [
          { required: true, message: "旧密码不能为空", trigger: "blur" }
        ],
        newPassword: [
          { validator: validateNewPassword, trigger: "blur" }
        ],
        confirmPassword: [
          { required: true, message: "确认密码不能为空", trigger: "blur" },
          { required: true, validator: equalToPassword, trigger: "blur" }
        ]
      }
    };
  },

3,重置密码

views/sysytem/user/index.vue

inputPattern:正则校验表达式

inputErrorMessage:校验不通过的提示信息

    /** 重置密码按钮操作 */
    handleResetPwd(row) {
      this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        closeOnClickModal: false,
        inputPattern: /^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*()_+={}\[\]|\\:;'",<>.?/-])[A-Za-z\d!@#$%^&*()_+={}\[\]|\\:;'",<>.?/-]{6,}$/,
        inputErrorMessage: "密码应至少6位且包含数字、大小写字母和特殊字符中的四种"
      }).then(({ value }) => {
        this.getPublicKey().then(res=> {
          let publicKey = res.publicKey
          const encryptValue = encrypt(value,publicKey)
          resetUserPwd(row.userId, encryptValue).then(response => {
            this.$modal.msgSuccess("修改成功,新密码是:" + value);
          });
        })

      }).catch(() => {});
    },

四,修改默认密码

sys_config表中config_key列sys.user.initPassword这一行对应的config_value改成默认密码,记得备注remark列也同步修改。

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于 Spring Boot 项目中的配置文件,我们可以使用 Jasypt(Java Simplified Encryption)来加密明文密码。Jasypt 提供了一个简单的 API 来在代码中加密和解密数据。以下是实现步骤: 1. 添加 Jasypt 依赖 在 pom.xml 文件中添加 Jasypt 依赖: ```xml <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> ``` 2. 配置加密算法 在 application.properties 文件中添加以下配置: ```properties jasypt.encryptor.algorithm=PBEWithMD5AndDES ``` 这里使用的是 PBEWithMD5AndDES 加密算法,可以根据需要选择其他算法。 3. 加密明文密码 使用 Jasypt 提供的 API 对密码进行加密。例如,我们想要加密的密码为 "123456",可以使用以下代码进行加密: ```java import org.jasypt.util.password.StrongPasswordEncryptor; String password = "123456"; StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor(); String encryptedPassword = passwordEncryptor.encryptPassword(password); System.out.println(encryptedPassword); ``` 将加密后的结果(例如,"EBXzrCJLxKZUeMl6x1cF8Q==")复制到配置文件中的密码字段中。 4. 解密密码 在代码中可以使用以下方法解密加密后的密码: ```java import org.jasypt.util.password.StrongPasswordEncryptor; String password = "123456"; String encryptedPassword = "EBXzrCJLxKZUeMl6x1cF8Q=="; StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor(); boolean isPasswordCorrect = passwordEncryptor.checkPassword(password, encryptedPassword); System.out.println(isPasswordCorrect); ``` 这里的 isPasswordCorrect 变量将会是 true,表示密码正确。 通过以上步骤,我们就可以在 Spring Boot 项目中安全地加密配置文件中的明文密码了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值