两次MD5
- 用户端:PASS = MD5(明文+固定Salt)
- 服务端:DBPASS = MD5(用户输入PASS+随机Salt)
HTTP使用明文传输,为了防止明文密码在网络传输,用户输入的明文密码MD5加密后再进行传输,
服务端接收到加密的密码后,为了防止数据库被盗后,通过彩虹表攻击查表获得密码,需要再次MD5加密,将加密结果和Salt写入数据库
添加依赖
<!--MD5工具类-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
工具类
MD5Util工具类
public class MD5Util {
public static String md5(String src) {
return DigestUtils.md5Hex(src);
}
private static final String salt = "1a2b3c4d"; //客户端固定salt
用户输入的密码转换成客户端提交的密码
public static String inputPassToFormPass(String inputPass) {
String str = "" +salt.charAt(0) + salt.charAt(2) + inputPass + salt.charAt(5) + salt.charAt(4);
return md5(str);
}
//客户端提交的密码转换成数据库存入的密码
public static String formPassToDBPass(String formPass, String salt) { //使用随机Salt
String str = "" +salt.charAt(0) + salt.charAt(2) + formPass + salt.charAt(5) + salt.charAt(4);
return md5(str);
}
public static String inputPassToDBPass(String input, String saltDB) {
String formPass = inputPassToFormPass(input);
String dbPass = formPassToDBPass(formPass, saltDB);
return dbPass;
}
}
前端
在另一个js文件中保存客户端固定的salt,客户端提交输入,对明文密码做第一次MD5
function doLogin() {
g_showLoading();
var inputPass = $("#password").val();
var salt = g_passsword_salt;//同上边工具类的客户端salt一致
//同上边工具类的转换一致
var str = "" +salt.charAt(0) + salt.charAt(2) + inputPass + salt.charAt(5) + salt.charAt(4);
var password = md5(str);
$.ajax({
url:"/login/do_login",
type:"POST",
data:{
mobile:$("#mobile").val(),
password: password
},
success:function (res) {
layer.closeAll();
if (res.code == 0) {
layer.msg("成功");
window.location.href="/goods/to_list";
} else {
layer.msg(res.msg);
}
console.log(res);
},
error:function () {
layer.closeAll();
}
});
}
后端
LoginController
@RequestMapping("/do_login")
@ResponseBody
public Result<Boolean> doLogin(HttpServletResponse response, @Valid LoginVo loginVo) {
log.info(loginVo.toString());
//登录
userService.login(response, loginVo);
return Result.success(true);
}
MiaoshaUserService中 //对用户提交做第二次MD5后比对数据库
public String login(HttpServletResponse response, LoginVo loginVo) {
if (loginVo == null) {
throw new GlobalException(CodeMsg.SERVER_ERROR);
}
String mobile = loginVo.getMobile();
String formPass = loginVo.getPassword();
//判断手机号是否存在
MiaoshaUser user = getById(Long.parseLong(mobile));
if (user == null) {
throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
}
//验证密码
String dbPass = user.getPassword();
String saltDB = user.getSalt();
String calcPass = MD5Util.formPassToDBPass(formPass, saltDB);
if (!calcPass.equals(dbPass)) {
throw new GlobalException(CodeMsg.PASSWORD_ERROR);
}
//生成token,Cookie,将token和对应用户写入第三方缓存redis
String token = UUIDUtil.uuid();
addCookie(user, response, token);
return token;
}