今天被吐槽在客戶端用js對密碼進行md5加密其實也不見得安全。這種做法其實不見得有什么作用,學過計算機網絡都知道,在網上抓一個包是很簡單的事,就算別人抓包抓不到你原始密碼,用這個md5后的密碼一樣可以模擬登錄系統。這樣做無非就是直接通過登錄頁沒法直接輸入用戶名密碼,但用個程序模擬登陸也不是什么太難的事情。以前一直寫那么多,一直沒有注意,直到今天被吐槽,才發現以前自己的做法是多么的幼稚。
加密數據的方式當然不止一種,也可以通過https加密數據,但是對於一般應用來說,還需要花錢拿去給那些認證機構簽名,反正我是不會干的,企業需要就另說。讓認證機構簽名了還不行,還需要讓用戶安裝證書,這么麻煩的事,用戶不一定要瀏覽你的網頁的時候,你的網頁就失去了一個展示的機會,而且畢竟不是所有用戶都有那么高的計算機操作水平。
使用RSA非對稱加密算法最適合我了,又不用錢,又比較安全。對稱加密也許大家都已經很熟悉,也就是加密和解密用的都是同樣的密鑰,沒有密鑰,就無法解密,這是對稱加密。而非對稱加密算法中,加密所用的密鑰和解密所用的密鑰是不相同的:你使用我的公鑰加密,我使用我的私鑰來解密;如果你不使用我的公鑰加密,那我無法解密;如果我沒有私鑰,我也沒法解密。
使用RSA的一個大概流程:
1、瀏覽器發起登陸請求
2、服務器響應請求,生成RSA公鑰和私鑰,並將公鑰返回瀏覽器
3、用戶輸入密碼后,用公鑰對密碼加密
4、將加密的密碼提交到服務器
5、使用私鑰解密密碼
使用RSA算法的主要注意事項大概有:
1、加入security.js的js文件,和加入一個bcprov-jdk16-1.45.jar的包
2、前端
<script src="<c:url value="/js/security.js"/>" type="text/javascript" ></script> <script type="text/javascript"> function cmdEncrypt(form) { RSAUtils.setMaxDigits(200); var key = new RSAUtils.getKeyPair("${pubexponent}", "", "${pubmodules}"); var encrypedPwd = RSAUtils.encryptedString(key,form.password.value); form.password.value = encrypedPwd; form.submit(); return true; } </script>
3、服務器
@RequestMapping(value="/login",method=RequestMethod.GET) public String login(Model model,HttpServletRequest request) throws Exception{ KeyPair kp = RSAUtil.generateKeyPair(); RSAPublicKey pubk = (RSAPublicKey) kp.getPublic();//生成公鑰 RSAPrivateKey prik= (RSAPrivateKey) kp.getPrivate();//生成私鑰 String publicKeyExponent = pubk.getPublicExponent().toString(16);//16進制 String publicKeyModulus = pubk.getModulus().toString(16);//16進制 model.addAttribute("pubexponent", publicKeyExponent);//保存公鑰指數 model.addAttribute("pubmodules", publicKeyModulus);//保存公鑰系數 request.getSession().setAttribute("prik", prik); return "login"; }
@RequestMapping(value="/login",method=RequestMethod.POST) public String login( LoginModel lm,HttpServletRequest request,Model model) throws Exception{
RSAPrivateKey prik = (RSAPrivateKey)request.getSession().getAttribute("prik"); StringBuilder pwd = new StringBuilder(); pwd.append(RSAUtil.decryptByPrivateKey(lm.getPassword().toUpperCase(), prik)).reverse();//反轉獲得的字符串 List<User> users = userService.getByLoginName(lm.getLoginName(),pwd.toString()); model.addAttribute("user", users.get(0)); return "redirect:/home/main"; }
4、在這幾個過程需要注意的是:
1)、pwd.append(RSAUtil.decryptByPrivateKey(lm.getPassword().toUpperCase(), prik)).reverse();獲得字符串需要反轉
以上用到的文件,可以在這里下載
這是個人經驗所得,有錯誤歡迎大家指出。