做社情网站犯法怎么办,做教育网站挣钱,自定义wordpress页面,wordpress制作分页#x1f3e1;浩泽学编程#xff1a;个人主页 #x1f525; 推荐专栏#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》 #x1f6f8;学无止境#xff0c;不骄不躁#xff0c;知行合一 文章目录 前言一、salt… 浩泽学编程个人主页 推荐专栏《深入浅出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.blocksblocks,this.buffer8buffer8;else if(ARRAY_BUFFER){var rnew ArrayBuffer(68);this.buffer8new Uint8Array(r),this.blocksnew Uint32Array(r)}else this.blocks[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];this.h0this.h1this.h2this.h3this.startthis.bytesthis.hBytes0,this.finalizedthis.hashed!1,this.first!0}var ERRORinput is invalid type,WINDOWobjecttypeof window,rootWINDOW?window:{};root.JS_MD5_NO_WINDOW(WINDOW!1);var WEB_WORKER!WINDOWobjecttypeof self,NODE_JS!root.JS_MD5_NO_NODE_JSobjecttypeof processprocess.versionsprocess.versions.node;NODE_JS?rootglobal:WEB_WORKER(rootself);var COMMON_JS!root.JS_MD5_NO_COMMON_JSobjecttypeof modulemodule.exports,AMDfunctiontypeof definedefine.amd,ARRAY_BUFFER!root.JS_MD5_NO_ARRAY_BUFFERundefined!typeof ArrayBuffer,HEX_CHARS0123456789abcdef.split(),EXTRA[128,32768,8388608,-2147483648],SHIFT[0,8,16,24],OUTPUT_TYPES[hex,array,digest,buffer,arrayBuffer,base64],BASE64_ENCODE_CHARABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/.split(),blocks[],buffer8;if(ARRAY_BUFFER){var buffernew ArrayBuffer(68);buffer8new Uint8Array(buffer),blocksnew Uint32Array(buffer)}(root.JS_MD5_NO_NODE_JS||!Array.isArray)(Array.isArrayfunction(t){return[object Array]Object.prototype.toString.call(t)}),!ARRAY_BUFFER||!root.JS_MD5_NO_ARRAY_BUFFER_IS_VIEWArrayBuffer.isView||(ArrayBuffer.isViewfunction(t){returnobjecttypeof tt.buffert.buffer.constructorArrayBuffer});var createOutputMethodfunction(t){return function(r){return new Md5(!0).update(r)[t]()}},createMethodfunction(){var tcreateOutputMethod(hex);NODE_JS(tnodeWrap(t)),t.createfunction(){return new Md5},t.updatefunction(r){return t.create().update(r)};for(var r0;rOUTPUT_TYPES.length;r){var eOUTPUT_TYPES[r];t[e]createOutputMethod(e)}return t},nodeWrapfunction(method){var cryptoeval(require(crypto)),Buffereval(require(buffer).Buffer),nodeMethodfunction(t){if(stringtypeof t)return crypto.createHash(md5).update(t,utf8).digest(hex);if(nullt||void 0t)throw ERROR;return t.constructorArrayBuffer(tnew Uint8Array(t)),Array.isArray(t)||ArrayBuffer.isView(t)||t.constructorBuffer?crypto.createHash(md5).update(new Buffer(t)).digest(hex):method(t)};return nodeMethod};Md5.prototype.updatefunction(t){if(!this.finalized){var r,etypeof t;if(string!e){if(object!e)throw ERROR;if(nullt)throw ERROR;if(ARRAY_BUFFERt.constructorArrayBuffer)tnew Uint8Array(t);else if(!(Array.isArray(t)||ARRAY_BUFFERArrayBuffer.isView(t)))throw ERROR;r!0}for(var s,i,o0,ht.length,fthis.blocks,athis.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(ithis.start;ho64i;o)a[i]t[o];else for(ithis.start;ho64i;o)f[i2]|t[o]SHIFT[3i];else if(ARRAY_BUFFER)for(ithis.start;ho64i;o)st.charCodeAt(o),128s?a[i]s:2048s?(a[i]192|s6,a[i]128|63s):55296s||s57344?(a[i]224|s12,a[i]128|s663,a[i]128|63s):(s65536((1023s)10|1023t.charCodeAt(o)),a[i]240|s18,a[i]128|s1263,a[i]128|s663,a[i]128|63s);else for(ithis.start;ho64i;o)st.charCodeAt(o),128s?f[i2]|sSHIFT[3i]:2048s?(f[i2]|(192|s6)SHIFT[3i],f[i2]|(128|63s)SHIFT[3i]):55296s||s57344?(f[i2]|(224|s12)SHIFT[3i],f[i2]|(128|s663)SHIFT[3i],f[i2]|(128|63s)SHIFT[3i]):(s65536((1023s)10|1023t.charCodeAt(o)),f[i2]|(240|s18)SHIFT[3i],f[i2]|(128|s1263)SHIFT[3i],f[i2]|(128|s663)SHIFT[3i],f[i2]|(128|63s)SHIFT[3i]);this.lastByteIndexi,this.bytesi-this.start,i64?(this.starti-64,this.hash(),this.hashed!0):this.starti}return this.bytes4294967295(this.hBytesthis.bytes/42949672960,this.bytesthis.bytes%4294967296),this}},Md5.prototype.finalizefunction(){if(!this.finalized){this.finalized!0;var tthis.blocks,rthis.lastByteIndex;t[r2]|EXTRA[3r],r56(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.bytes3,t[15]this.hBytes3|this.bytes29,this.hash()}},Md5.prototype.hashfunction(){var t,r,e,s,i,o,hthis.blocks;this.first?(th[0]-680876937,t(t7|t25)-2717338790,s(-1732584194^2004318071t)h[1]-117830708,s(s12|s20)t0,e(-271733879^s(-271733879^t))h[2]-1126478375,e(e17|e15)s0,r(t^e(s^t))h[3]-1316259209,r(r22|r10)e0):(tthis.h0,rthis.h1,ethis.h2,sthis.h3,t(s^r(e^s))h[0]-680876936,t(t7|t25)r0,s(e^t(r^e))h[1]-389564586,s(s12|s20)t0,e(r^s(t^r))h[2]606105819,e(e17|e15)s0,r(t^e(s^t))h[3]-1044525330,r(r22|r10)e0),t(s^r(e^s))h[4]-176418897,t(t7|t25)r0,s(e^t(r^e))h[5]1200080426,s(s12|s20)t0,e(r^s(t^r))h[6]-1473231341,e(e17|e15)s0,r(t^e(s^t))h[7]-45705983,r(r22|r10)e0,t(s^r(e^s))h[8]1770035416,t(t7|t25)r0,s(e^t(r^e))h[9]-1958414417,s(s12|s20)t0,e(r^s(t^r))h[10]-42063,e(e17|e15)s0,r(t^e(s^t))h[11]-1990404162,r(r22|r10)e0,t(s^r(e^s))h[12]1804603682,t(t7|t25)r0,s(e^t(r^e))h[13]-40341101,s(s12|s20)t0,e(r^s(t^r))h[14]-1502002290,e(e17|e15)s0,r(t^e(s^t))h[15]1236535329,r(r22|r10)e0,t(e^s(r^e))h[1]-165796510,t(t5|t27)r0,s(r^e(t^r))h[6]-1069501632,s(s9|s23)t0,e(t^r(s^t))h[11]643717713,e(e14|e18)s0,r(s^t(e^s))h[0]-373897302,r(r20|r12)e0,t(e^s(r^e))h[5]-701558691,t(t5|t27)r0,s(r^e(t^r))h[10]38016083,s(s9|s23)t0,e(t^r(s^t))h[15]-660478335,e(e14|e18)s0,r(s^t(e^s))h[4]-405537848,r(r20|r12)e0,t(e^s(r^e))h[9]568446438,t(t5|t27)r0,s(r^e(t^r))h[14]-1019803690,s(s9|s23)t0,e(t^r(s^t))h[3]-187363961,e(e14|e18)s0,r(s^t(e^s))h[8]1163531501,r(r20|r12)e0,t(e^s(r^e))h[13]-1444681467,t(t5|t27)r0,s(r^e(t^r))h[2]-51403784,s(s9|s23)t0,e(t^r(s^t))h[7]1735328473,e(e14|e18)s0,r(s^t(e^s))h[12]-1926607734,r(r20|r12)e0,ir^e,t(i^s)h[5]-378558,t(t4|t28)r0,s(i^t)h[8]-2022574463,s(s11|s21)t0,os^t,e(o^r)h[11]1839030562,e(e16|e16)s0,r(o^e)h[14]-35309556,r(r23|r9)e0,ir^e,t(i^s)h[1]-1530992060,t(t4|t28)r0,s(i^t)h[4]1272893353,s(s11|s21)t0,os^t,e(o^r)h[7]-155497632,e(e16|e16)s0,r(o^e)h[10]-1094730640,r(r23|r9)e0,ir^e,t(i^s)h[13]681279174,t(t4|t28)r0,s(i^t)h[0]-358537222,s(s11|s21)t0,os^t,e(o^r)h[3]-722521979,e(e16|e16)s0,r(o^e)h[6]76029189,r(r23|r9)e0,ir^e,t(i^s)h[9]-640364487,t(t4|t28)r0,s(i^t)h[12]-421815835,s(s11|s21)t0,os^t,e(o^r)h[15]530742520,e(e16|e16)s0,r(o^e)h[2]-995338651,r(r23|r9)e0,t(e^(r|~s))h[0]-198630844,t(t6|t26)r0,s(r^(t|~e))h[7]1126891415,s(s10|s22)t0,e(t^(s|~r))h[14]-1416354905,e(e15|e17)s0,r(s^(e|~t))h[5]-57434055,r(r21|r11)e0,t(e^(r|~s))h[12]1700485571,t(t6|t26)r0,s(r^(t|~e))h[3]-1894986606,s(s10|s22)t0,e(t^(s|~r))h[10]-1051523,e(e15|e17)s0,r(s^(e|~t))h[1]-2054922799,r(r21|r11)e0,t(e^(r|~s))h[8]1873313359,t(t6|t26)r0,s(r^(t|~e))h[15]-30611744,s(s10|s22)t0,e(t^(s|~r))h[6]-1560198380,e(e15|e17)s0,r(s^(e|~t))h[13]1309151649,r(r21|r11)e0,t(e^(r|~s))h[4]-145523070,t(t6|t26)r0,s(r^(t|~e))h[11]-1120210379,s(s10|s22)t0,e(t^(s|~r))h[2]718787259,e(e15|e17)s0,r(s^(e|~t))h[9]-343485551,r(r21|r11)e0,this.first?(this.h0t17325841930,this.h1r-2717338790,this.h2e-17325841940,this.h3s2717338780,this.first!1):(this.h0this.h0t0,this.h1this.h1r0,this.h2this.h2e0,this.h3this.h3s0)},Md5.prototype.hexfunction(){this.finalize();var tthis.h0,rthis.h1,ethis.h2,sthis.h3;return HEX_CHARS[t415]HEX_CHARS[15t]HEX_CHARS[t1215]HEX_CHARS[t815]HEX_CHARS[t2015]HEX_CHARS[t1615]HEX_CHARS[t2815]HEX_CHARS[t2415]HEX_CHARS[r415]HEX_CHARS[15r]HEX_CHARS[r1215]HEX_CHARS[r815]HEX_CHARS[r2015]HEX_CHARS[r1615]HEX_CHARS[r2815]HEX_CHARS[r2415]HEX_CHARS[e415]HEX_CHARS[15e]HEX_CHARS[e1215]HEX_CHARS[e815]HEX_CHARS[e2015]HEX_CHARS[e1615]HEX_CHARS[e2815]HEX_CHARS[e2415]HEX_CHARS[s415]HEX_CHARS[15s]HEX_CHARS[s1215]HEX_CHARS[s815]HEX_CHARS[s2015]HEX_CHARS[s1615]HEX_CHARS[s2815]HEX_CHARS[s2415]},Md5.prototype.toStringMd5.prototype.hex,Md5.prototype.digestfunction(){this.finalize();var tthis.h0,rthis.h1,ethis.h2,sthis.h3;return[255t,t8255,t16255,t24255,255r,r8255,r16255,r24255,255e,e8255,e16255,e24255,255s,s8255,s16255,s24255]},Md5.prototype.arrayMd5.prototype.digest,Md5.prototype.arrayBufferfunction(){this.finalize();var tnew ArrayBuffer(16),rnew Uint32Array(t);return r[0]this.h0,r[1]this.h1,r[2]this.h2,r[3]this.h3,t},Md5.prototype.bufferMd5.prototype.arrayBuffer,Md5.prototype.base64function(){for(var t,r,e,s,ithis.array(),o0;15o;)ti[o],ri[o],ei[o],sBASE64_ENCODE_CHAR[t2]BASE64_ENCODE_CHAR[63(t4|r4)]BASE64_ENCODE_CHAR[63(r2|e6)]BASE64_ENCODE_CHAR[63e];return ti[o],sBASE64_ENCODE_CHAR[t2]BASE64_ENCODE_CHAR[t463]};var exportscreateMethod();COMMON_JS?module.exportsexports:(root.md5exports,AMDdefine(function(){return exports}))}();登录页面。其他样式及其他js文件不再给大家只需要关注手机号和密码输入框还有提交按钮就行主要在于实现登录。解释一下下面代码主要含义登录按钮绑定login函数在该函数中调用了dologin函数dologin中获取输入框输入密码然后取出盐值的其中4个字符串然后混合拼接到密码中然后使用MD5加密。最后使用ajax将加密后的密码封装到参数中。这样传输过程就不再是明文形式。而ajax是服务器端进行路径控制层拦截处理 login.html
!DOCTYPE html
html langenxmlns:thhttp://www.thymeleaf.org
headmeta charsetUTF-8title登录/title!-- jquery --script typetext/javascript th:src{/js/jquery.min.js}/script!-- bootstrap --link relstylesheet typetext/css th:href{/bootstrap/css/bootstrap.min.css}/script typetext/javascript th:src{/bootstrap/js/bootstrap.min.js}/script!-- jquery-validator --script typetext/javascript th:src{/jquery-validation/jquery.validate.min.js}/scriptscript typetext/javascript th:src{/jquery-validation/localization/messages_zh.min.js}/script!-- md5.js --script typetext/javascript th:src{/js/md5.min.js}/script!-- common.js --script typetext/javascript th:src{/js/common.js}/script
/head
body
form nameloginForm idloginForm methodpost stylewidth:50%; margin:0 autoh2 styletext-align:center; margin-bottom: 20px用户登录/h2div classform-groupdiv classrowlabel classform-label col-md-4请输入手机号码/labeldiv classcol-md-5input idmobile minlength11 maxlength11 namemobile classform-control typetext placeholder手机号码 requiredtrue//div/div/divdiv classform-groupdiv classrowlabel classform-label col-md-4请输入密码/labeldiv classcol-md-5input idpassword namepassword classform-control typepassword placeholder密码 requiredtrue //div/div/divdiv classrowdiv classcol-md-5button classbtn btn-primary btn-block typereset onclickreset()重置/button/divdiv classcol-md-5button classbtn btn-primary btn-block typesubmit onclicklogin()登录/button/div/div
/form
/body
scriptfunction login() {$(#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();}});}
/script
/html服务器端后端
引入依赖
dependencygroupIdcommons-codec/groupIdartifactIdcommons-codec/artifactId
/dependency
dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-lang3/artifactIdversion3.12.0/version
/dependency封装MD5加密解密工具类解释一下如下代码首先加密函数是随机生成一个16位盐值然后与传过来的密码拼接拼接后进行MD5加密这个盐值我们必须要保存的要不然我们自己也无法解密所以再将盐值按照自定义的方法插入加密后的密文中。然后在解密时根据这个方法取出盐值进行解密操作。 public class MD5Util {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 16) {for (int i 0; i 16 - len; i) {stringBuilder.append(0);}}// 生成盐String salt stringBuilder.toString();//将盐加到明文中并生成新的MD5码password md5(password salt);//将盐混到新生成的MD5码中之所以这样做是为了后期解密校验密码char[] cs new char[48];for (int i 0; i 48; i 3) {cs[i] password.charAt(i / 3 * 2);char c salt.charAt(i / 3);cs[i 1] c;cs[i 2] password.charAt(i / 3 * 2 1);}return new String(cs);}/*** 解密* 将混入MD5加密的密文中的盐取出来然后将传来的密码按照此盐进行MD5加密再比较**/public static boolean verifySaltPassword(String password, String md) {//先从MD5码中取出之前加的盐和加盐后生成的MD5码char[] cs1 new char[32];char[] cs2 new char[16];for (int i 0; i 48; i 3) {cs1[i / 3 * 2] md.charAt(i);cs1[i / 3 * 2 1] md.charAt(i 2);cs2[i / 3] md.charAt(i 1);}String salt new String(cs2);//比较二者是否相同return md5(password salt).equals(new String(cs1));}
}
这里我准备了个测试传过来个前端加密的密码进行加密再进行解密验证。 public static void main(String[] args) {String p1 generateSaltPassword(d3b1294a61a07da9b49b6e22b2cbd7f9);System.out.println(p1);System.out.println(verifySaltPassword(d3b1294a61a07da9b49b6e22b2cbd7f9,p1));}可以看到解密加密成功。 登录逻辑处理注重看登录逻辑一些工具类不再列出。 public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {String mobile loginVo.getMobile();String password loginVo.getPassword();
// if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)) {
// return RespBean.error(RespBeanEnum.LOGIN_ERROR);
// }
// if (!ValidatorUtil.isMobile(mobile)){
// return RespBean.error(RespBeanEnum.MOBILE_ERROR);
// }//根据手机号获取用户User user userMapper.selectById(mobile);if (null user) {throw new GlobalException(RespBeanEnum.LOGIN_ERROR);}// 获取数据库用户密码String saltPassword user.getPassword();//判断密码是否正确if (!MD5Util.verifySaltPassword(password, saltPassword)){throw new GlobalException(RespBeanEnum.LOGIN_ERROR);}//生成cookieString ticket UUIDUtil.uuid();redisTemplate.opsForValue().set(user: ticket,user);
// request.getSession().setAttribute(ticket,user);CookieUtil.setCookie(request,response,userTicker,ticket);return RespBean.success();}补充
随机盐的生成有很多方法比如生成UUID截取等。如果想更加复杂可以将盐中的字符串按照一定自定义方法插入到传来的密码中然后再MD5加密最后再将盐值插入其中。 总结
以上就是我做项目使用的登录加密技术随机盐值MD5双重加密。