🔥 推荐专栏:《深入浅出SpringBoot》《java对AI的调用开发》
《RabbitMQ》《Spring》《SpringMVC》
🛸学无止境,不骄不躁,知行合一
文章目录
- 前言
- 一、salt和MD5
- 简单认识
- 如何使用
- 二、具体实现
- 前端
- 服务器端(后端)
- 补充
- 总结
前言
SpringBoot+随机盐值+双重MD5实现加密登录。
一、salt和MD5
简单认识
加盐(盐英文就是salt):在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为”加盐“。
MD5信息摘要算法(英语:MD5 Message-Digest Algorithm):一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。
MD5原理:MD5码以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
说到这里,细心的朋友可以发现,你这不是说MD5可以被破解,存在弱点,现在的MD5破解工具也很多,你为什么还在使用呢。其实作为初学者,我们是一步步接触更好的技术,我也是在接触好技术的过程,对项目加密等问题也在不断完善,这是我学习过程使用到的加密技术,所以在此记录分享一下。并且随机盐与MD5融合破解难度大大增加,很难。
如何使用
两次MD5加密
- 用户端:PASS = MD5(明文,就是用户输入的密码;明文+固定Salt)
- 第一次MD5加密:前端传给后端时候,进行第一次MD5加密,防止密码在网络中以明文传输。
- 服务端:PASS = MD5(用户端PASS,就是前端加密后的密码;前端PASS+随机Salt)
- 第二次MD5加密:服务器端(后端)接收到MD5加密后的密码存入数据库之前进行第二次MD5加密。
- 这次加密采用的是随机生成盐值,然后与密码拼接,进行MD5加密,再将随机生成的盐值混合(按照自己设置的规律)到加密后的密码中存入数据库,这样就不会存在盐值随机造成的自己无法破解。
二、具体实现
前端
引入MD5的js文件
md5.min.js:直接给大家,节省大家寻找的时间,文件取名相同,复制粘贴即可。
/** * [js-md5]{@link https://github.com/emn178/js-md5} * * @namespace md5 * @version 0.7.2 */ !function(){"use strict";function Md5(t){if(t)blocks[0]=blocks[16]=blocks[1]=blocks[2]=blocks[3]=blocks[4]=blocks[5]=blocks[6]=blocks[7]=blocks[8]=blocks[9]=blocks[10]=blocks[11]=blocks[12]=blocks[13]=blocks[14]=blocks[15]=0,this.blocks=blocks,this.buffer8=buffer8;else if(ARRAY_BUFFER){var r=new ArrayBuffer(68);this.buffer8=new Uint8Array(r),this.blocks=new Uint32Array(r)}else this.blocks=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];this.h0=this.h1=this.h2=this.h3=this.start=this.bytes=this.hBytes=0,this.finalized=this.hashed=!1,this.first=!0}var ERROR="input is invalid type",WINDOW="object"==typeof window,root=WINDOW?window:{};root.JS_MD5_NO_WINDOW&&(WINDOW=!1);var WEB_WORKER=!WINDOW&&"object"==typeof self,NODE_JS=!root.JS_MD5_NO_NODE_JS&&"object"==typeof process&&process.versions&&process.versions.node;NODE_JS?root=global:WEB_WORKER&&(root=self);var COMMON_JS=!root.JS_MD5_NO_COMMON_JS&&"object"==typeof module&&module.exports,AMD="function"==typeof define&&define.amd,ARRAY_BUFFER=!root.JS_MD5_NO_ARRAY_BUFFER&&"undefined"!=typeof ArrayBuffer,HEX_CHARS="0123456789abcdef".split(""),EXTRA=[128,32768,8388608,-2147483648],SHIFT=[0,8,16,24],OUTPUT_TYPES=["hex","array","digest","buffer","arrayBuffer","base64"],BASE64_ENCODE_CHAR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""),blocks=[],buffer8;if(ARRAY_BUFFER){var buffer=new ArrayBuffer(68);buffer8=new Uint8Array(buffer),blocks=new Uint32Array(buffer)}(root.JS_MD5_NO_NODE_JS||!Array.isArray)&&(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),!ARRAY_BUFFER||!root.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW&&ArrayBuffer.isView||(ArrayBuffer.isView=function(t){return"object"==typeof t&&t.buffer&&t.buffer.constructor===ArrayBuffer});var createOutputMethod=function(t){return function(r){return new Md5(!0).update(r)[t]()}},createMethod=function(){var t=createOutputMethod("hex");NODE_JS&&(t=nodeWrap(t)),t.create=function(){return new Md5},t.update=function(r){return t.create().update(r)};for(var r=0;rvar e=OUTPUT_TYPES[r];t[e]=createOutputMethod(e)}return t},nodeWrap=function(method){var crypto=eval("require('crypto')"),Buffer=eval("require('buffer').Buffer"),nodeMethod=function(t){if("string"==typeof t)return crypto.createHash("md5").update(t,"utf8").digest("hex");if(null===t||void 0===t)throw ERROR;return t.constructor===ArrayBuffer&&(t=new Uint8Array(t)),Array.isArray(t)||ArrayBuffer.isView(t)||t.constructor===Buffer?crypto.createHash("md5").update(new Buffer(t)).digest("hex"):method(t)};return nodeMethod};Md5.prototype.update=function(t){if(!this.finalized){var r,e=typeof t;if("string"!==e){if("object"!==e)throw ERROR;if(null===t)throw ERROR;if(ARRAY_BUFFER&&t.constructor===ArrayBuffer)t=new Uint8Array(t);else if(!(Array.isArray(t)||ARRAY_BUFFER&&ArrayBuffer.isView(t)))throw ERROR;r=!0}for(var s,i,o=0,h=t.length,f=this.blocks,a=this.buffer8;ho;){if(this.hashed&&(this.hashed=!1,f[0]=f[16],f[16]=f[1]=f[2]=f[3]=f[4]=f[5]=f[6]=f[7]=f[8]=f[9]=f[10]=f[11]=f[12]=f[13]=f[14]=f[15]=0),r)if(ARRAY_BUFFER)for(i=this.start;h>o&&64>i;++o)a[i++]=t[o];else for(i=this.start;h>o&&64>i;++o)f[i>>2]|=t[o]i;++o)s=t.charCodeAt(o),128>s?a[i++]=s:2048>s?(a[i++]=192|s>>6,a[i++]=128|63&s):55296>s||s>=57344?(a[i++]=224|s>>12,a[i++]=128|s>>6&63,a[i++]=128|63&s):(s=65536+((1023&s)18,a[i++]=128|s>>12&63,a[i++]=128|s>>6&63,a[i++]=128|63&s);else for(i=this.start;h>o&&64>i;++o)s=t.charCodeAt(o),128>s?f[i>>2]|=s>2]|=(192|s>>6)2]|=(128|63&s)=57344?(f[i>>2]|=(224|s>>12)2]|=(128|s>>6&63)2]|=(128|63&s)18)2]|=(128|s>>12&63)2]|=(128|s>>6&63)2]|=(128|63&s)4294967295&&(this.hBytes+=this.bytes/4294967296if(!this.finalized){this.finalized=!0;var t=this.blocks,r=this.lastByteIndex;t[r2]|=EXTRA[3&r],r>=56&&(this.hashed||this.hash(),t[0]=t[16],t[16]=t[1]=t[2]=t[3]=t[4]=t[5]=t[6]=t[7]=t[8]=t[9]=t[10]=t[11]=t[12]=t[13]=t[14]=t[15]=0),t[14]=this.bytesvar t,r,e,s,i,o,h=this.blocks;this.first?(t=h[0]-680876937,t=(tthis.finalize();var t=this.h0,r=this.h1,e=this.h2,s=this.h3;return HEX_CHARS[t4&15]+HEX_CHARS[15&t]+HEX_CHARS[t12&15]+HEX_CHARS[t8&15]+HEX_CHARS[t20&15]+HEX_CHARS[t16&15]+HEX_CHARS[t28&15]+HEX_CHARS[t24&15]+HEX_CHARS[r4&15]+HEX_CHARS[15&r]+HEX_CHARS[r12&15]+HEX_CHARS[r8&15]+HEX_CHARS[r20&15]+HEX_CHARS[r16&15]+HEX_CHARS[r28&15]+HEX_CHARS[r24&15]+HEX_CHARS[e4&15]+HEX_CHARS[15&e]+HEX_CHARS[e12&15]+HEX_CHARS[e8&15]+HEX_CHARS[e20&15]+HEX_CHARS[e16&15]+HEX_CHARS[e28&15]+HEX_CHARS[e24&15]+HEX_CHARS[s4&15]+HEX_CHARS[15&s]+HEX_CHARS[s12&15]+HEX_CHARS[s8&15]+HEX_CHARS[s20&15]+HEX_CHARS[s16&15]+HEX_CHARS[s28&15]+HEX_CHARS[s24&15]},Md5.prototype.toString=Md5.prototype.hex,Md5.prototype.digest=function(){this.finalize();var t=this.h0,r=this.h1,e=this.h2,s=this.h3;return[255&t,t8&255,t16&255,t24&255,255&r,r8&255,r16&255,r24&255,255&e,e8&255,e16&255,e24&255,255&s,s8&255,s16&255,s24&255]},Md5.prototype.array=Md5.prototype.digest,Md5.prototype.arrayBuffer=function(){this.finalize();var t=new ArrayBuffer(16),r=new Uint32Array(t);return r[0]=this.h0,r[1]=this.h1,r[2]=this.h2,r[3]=this.h3,t},Md5.prototype.buffer=Md5.prototype.arrayBuffer,Md5.prototype.base64=function(){for(var t,r,e,s="",i=this.array(),o=0;15o;)t=i[o++],r=i[o++],e=i[o++],s+=BASE64_ENCODE_CHAR[t2]+BASE64_ENCODE_CHAR[63&(t6)]+BASE64_ENCODE_CHAR[63&e];return t=i[o],s+=BASE64_ENCODE_CHAR[t>>>2]+BASE64_ENCODE_CHAR[treturn exports}))}(); $("#loginForm").validate({ submitHandler: function (form) { doLogin(); } }); } function doLogin() { var inputPass = $("#password").val(); var salt = "1a2b3c4d"; var str = "" + salt.charAt(0) + salt.charAt(2) + inputPass + salt.charAt(5) + salt.charAt(4); var password = md5(str); $.ajax({ url: "/login/doLogin", type: "POST", data: { mobile: $("#mobile").val(), password: password }, success: function (data) { layer.closeAll(); if (data.code == 200) { layer.msg("成功"); console.log(data); document.cookie = "userTicket=" + data.object; window.location.href = "/goods/toList"; } else { layer.msg(data.message); } }, error: function () { layer.closeAll(); } }); } public static String md5(String str){ return DigestUtils.md5Hex(str); } /** * 加密 * 生成盐和加盐后的MD5码,并将盐混入到MD5码中,对MD5密码进行加强 **/ public static String generateSaltPassword(String password) { Random random = new Random(); /** * 生成一个16位的随机数,也就是盐 **/ StringBuilder stringBuilder = new StringBuilder(16); stringBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999)); int len = stringBuilder.length(); if (len
- 用户端:PASS = MD5(明文,就是用户输入的密码;明文+固定Salt)