效果图
表单提交加密后的密文
软件环境
apollo配置中心,官方下载地址: https://github.com/apolloconfig/apollo
apollo配置中心,官方文档:Apollo
前端加密工具:https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js
解密工具:hutool-all 5.8.36 官方网址:https://github.com/chinabugotech/hutool
解密(底层实现)工具:bcprov-jdk18on 1.80 官方网址: Download Bouncy Castle Java - Bouncycastle
需求说明
1、登陆页面表单密码加密
2、不能影响现有功能和性能
登陆页面Javascript 做密码加密
二开login.html
<!-- 引入js加密组件 -->
<script src="crypto-js.min.js"></script>
//已有其他代码。。。。。
<!-- 找到现有的js代码段加入下面的js -->
<script type="application/javascript">
document.getElementById('login-form').addEventListener('submit', function(e) {
e.preventDefault(); // 阻止表单默认提交行为
var password = document.getElementById('password').value;
// 记住一定要16的整数个字符,不建议使用中文和特殊字符
var saltStr="1234567890123456";
var key = CryptoJS.enc.Utf8.parse(saltStr);
// 使用AES加密
var encryptedPassword = CryptoJS.AES.encrypt(password, key,{
mode: CryptoJS.mode.ECB, // 加密模式,例如ECB、CBC等
padding: CryptoJS.pad.Pkcs7 // 填充模式,例如Pkcs7、Iso97971等
}).toString(); // 使用AES加密
console.log(encryptedPassword)
document.getElementById("password").value=encryptedPassword;
// 可以在这里将加密后的密码发送到服务器,例如通过Ajax
sendDataToServer( );
});
/** 解决了提交事件循环执行的问题 **/
function sendDataToServer(encryptedPassword) {
document.getElementById('login-form').submit();
};
.... // 其它已有代码
</script>
说明:

这里加密用的盐写死在js中了,读者可自行改造,如记配置中心中,前后台代码都中配置中心取
maven配置
pom.xml
说明:
登陆表单增加验证码见作者另一篇文章:Apollo配置中心登陆页面添加验证码-CSDN博客
<!-- 工具包,包含验证码、加解密(无底层实现) -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.36</version>
</dependency>
<!-- 加解密(底层实现),低版本的可能需要升级 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.80</version>
</dependency>
小知识:
一般bcprov包并非直接引用,升级自带加解密包时可从对应依赖中先排除 ,然后添加新版本pom依赖。
二开LoginAuthenticationProvider
这里使用默认的加密模式ECB、填充模式Pkcs7
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import Constant;
import java.util.Collection;
public class LoginAuthenticationProvider implements AuthenticationProvider
{
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
/**
* 验证登录信息,若登陆成功,设置 Authentication
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
// 解密
// AES密钥,长度为16/24/32字节
// 初始化AES对象
AES aes = null;
aes = SecureUtil.aes(Constant.SALT_KEY.getBytes());
// System.out.println("解密前的数据: " + password);
// 解密Base64格式的加密数据
password = new String(aes.decrypt(password));
// 输出解密后的数据
// System.out.println("解密后的数据: " + password);
UserDetails user = userDetailsService.loadUserByUsername(username);
if (passwordEncoder.matches(password, user.getPassword())) {
Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
return new UsernamePasswordAuthenticationToken(username, password, authorities);
}
throw new BadCredentialsException("The password is not correct.");
}
/**
* 当前 Provider 是否支持对该类型的凭证提供认证服务
*/
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.equals(authentication);
}
}
盐常量类
/**
* @Description: 常量类
* @Author: brickerman
* @CreateDate: 2025/4/3 15:06
* @Version: 1.0
*/
public class Constant {
public static final String SALT_KEY="1234567890123456";
}
附件一:AES加解密简介
AES(Advanced Encryption Standard)是一种对称加密算法,由美国国家标准与技术研究院(NIST)在2001年发布,旨在取代数据加密标准(DES)。 AES算法使用相同的密钥进行加密和解密操作,具有高效、安全和灵活的特点,适用于多种平台和环境。
AES加密的基本原理
AES算法通过多轮次的置换-置换网络(SPN)结构来实现加密过程。每轮操作包括以下四个步骤:
- 字节替换(SubBytes):使用一个称为S盒的固定置换表来替换输入数据的每个字节,增加数据的混淆程度。
- 行移位(ShiftRows):将数据块中的每一行进行循环左移,不同行的移动距离不同,进一步扩散数据。
- 列混合(MixColumns):使用一个固定的矩阵与数据块的每一列进行矩阵乘法运算,增强非线性性。
- 添加轮密钥(AddRoundKey):将每轮的轮密钥与数据块进行异或操作。
AES加密模式
AES支持多种加密模式,常见的有:
- ECB(Electronic Codebook)模式:将每个分组独立加密,适用于对称性较弱的数据,但安全性较低。
- CBC(Cipher Block Chaining)模式:前一个分组的密文与当前分组的明文进行异或操作后再加密,增加了分组之间的关联性,安全性较高。
- CTR(Counter)模式:通过计数器生成密钥流,适用于流式数据传输,如视频和音频流媒体,速度快。
- CFB(Cipher Feedback)模式:类似于CTR模式,但使用可变长度的密钥,适用于需要反馈的场景。
AES的应用场景
AES被广泛应用于各种领域:
- 数据保护:用于保护敏感数据,如金融信息、个人身份信息等。
- VPN和TLS:在虚拟私人网络和传输层安全协议中用于数据加密。
- 文件加密:用于加密文件和存储设备,保护数据隐私。
- 电子商务:在在线支付和交易中保障数据安全。