SpringBoot + Vue 前后端加密登录实现(基于 Xboot 框架)

SpringBoot + Vue 前后端加密登录实现(基于 Xboot 框架)

解决前后端登录时密码明文暴露的问题,增强登录安全性。

背景问题
在使用 Vue + SpringBoot(Xboot 框架)开发的管理系统中,用户登录时密码通过 POST 请求明文传输,即使是 HTTPS,也会暴露在浏览器控制台的请求中:
控制台中密码明文显示
目标效果
前端使用 RSA 公钥加密密码,后端使用 RSA 私钥解密密码,从而实现:
浏览器控制台不再显示明文密码;
不影响原有的登录认证逻辑;

实现方式
第一步:前端使用 RSA 公钥加密密码 (使用Java生成PEM 密钥,代码在末尾)
第二步:后端替换默认登录过滤器,在认证前使用私钥解密
详细实现步骤
一、前端加密(Vue 端)
1. 安装依赖
npm install jsencrypt --save
2. 修改登录方法

import { JSEncrypt } from 'jsencrypt';
export default {
  data() {
    return {
      form: {
        username: "",
        password: "",
      },
      publicKey: '"xxxxx",  // 直接写死。
    }
  },
//  async created() {
//    const res = await this.getRequest('/publicKey');
//    this.publicKey = res.publicKey;
//  },
  methods: {
    submitLogin() {
      const encryptor = new JSEncrypt();
      const pemKey = `-----BEGIN PUBLIC KEY-----\n${this.publicKey.match(/.{1,64}/g).join('\n')}\n-----END PUBLIC KEY-----`;
      encryptor.setPublicKey(pemKey);
      const encryptedPwd = encryptor.encrypt(this.form.password);
      if (!encryptedPwd) {
        this.$Message.error("密码加密失败,请重试");
        return;
      }
      login({
        username: this.form.username,
        password: encryptedPwd
      }).then(res => {
        // 登录成功处理逻辑
      });
    }
  }
}

二、后端解密(SpringBoot + Security)
1.添加密钥配置
如图所示
2. 创建 RSA 解密服务类
RsaDecryptService.java:

@Service
public class RsaDecryptService {

    @Value("${rsa.privateKey}")
    private String privateKeyBase64;

    public String decrypt(String cipherText) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(privateKeyBase64);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(spec);

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        byte[] decoded = Base64.getDecoder().decode(cipherText);
        byte[] decrypted = cipher.doFinal(decoded);
        return new String(decrypted, StandardCharsets.UTF_8);
    }
}

3. 替换默认登录过滤器
RsaAuthenticationFilter.java:

public class RsaAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private final RsaDecryptService rsaDecryptService;

    public RsaAuthenticationFilter(RsaDecryptService rsaDecryptService) {
        this.rsaDecryptService = rsaDecryptService;
        this.setFilterProcessesUrl("/xboot/login");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {

        String username = obtainUsername(request);
        String encryptedPassword = obtainPassword(request);

        try {
            String rawPassword = rsaDecryptService.decrypt(encryptedPassword);
            return this.getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken(username, rawPassword)
            );
        } catch (Exception e) {
            throw new AuthenticationServiceException("RSA password decrypt failed", e);
        }
    }
}

4. 修改 WebSecurityConfig 注册你的过滤器

修改webSecurityConfig类中的configure方法。

RsaAuthenticationFilter rsaFilter = new RsaAuthenticationFilter(rsaDecryptService);
rsaFilter.setAuthenticationManager(authenticationManager());
rsaFilter.setAuthenticationSuccessHandler(successHandler);
rsaFilter.setAuthenticationFailureHandler(failHandler);

加上以上代码,如下图所示,同时记得加上

.addFilterAt(rsaFilter, UsernamePasswordAuthenticationFilter.class) 

替换默认的UsernamePasswordAuthenticationFilter 为你自己的
记得替换
密钥生成工具(Java 生成 PEM 密钥)

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Base64;

/*登录加密*/
public class LoginSec {
    public static void main(String[] args) throws Exception {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(2048);
        KeyPair keyPair = kpg.generateKeyPair();

        String pub = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        String pri = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());

        System.out.println("公钥: " + pub);
        System.out.println("私钥: " + pri);

    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值