今天被吐槽在客戶端用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();獲得字串需要反轉
以上用到的檔案,可以在這裡下載
這是個人經驗所得,有錯誤歡迎大家指出。