上次面试的时候问到了系统用的安全机制是什么,瞬间就懵了,查了资料才知道我们系统用了MD5。真的是要多多学习,特意写了博客记录下来。此篇博客参考了下面两位朋友的,如觉不妥联系必删。
http://blog.youkuaiyun.com/lmq321281/article/details/50998840
http://blog.youkuaiyun.com/vi_error/article/details/72529218#t0
MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)
使用这种机制时,client与server共享同一个隐性密码,而且此密码不通过网络传输。验证过程是从服务器先提出challenge(质询)开始, 客户端使用此challenge与隐性密码计算出一个response(应答)。不同的challenge,不可能计算出相同的response;任何拥 有secret password的一方,都可以用相同的challenge算出相同的response。因此,服务器只要比较客户端返回的response是否与自己算 出的response相同,就可以知道客户端所拥有的密码是否正确。由于真正的密码并没有通过网络,所以不怕网络监测。
MD5常常作为文件的签名出现,我们在下载文件的时候,常常会看到文件页面上附带一个扩展名为.MD5的文本或者一行字符,这行字符就是就是把整个文件当作原数据通过MD5计算后的值,我们下载文件后,可以用检查文件MD5信息的软件对下载到的文件在进行一次计算。两次结果对比就可以确保下载到文件的准确性。
网站敏感信息加密,比如用户名密码,支付签名等等。随着https技术的普及,现在的网站广泛采用前台明文传输到后台,MD5加密(使用偏移量)的方式保护敏感数据保护站点和数据安全。
抛去MD5的安全性不讲,由于MD5算法是公开的,所有人都可以获得和使用MD5算法,如果不对MD5算法进行一些处理,那么当我们将自己的重要接口暴露在互联网上的时候,比如登陆接口,攻击者就可以同样利用MD5加密算法对我们进行撞库攻击和关键信息比对。我们应当如何处理这种情况呢?
首先肯定是整个应用程序的流控,限制单个IP、单个用户、非法IP的不正常访问,这些能够很大程度上避免攻击者不受限制的调用我们的接口撞库攻击。
Tips:流控是一个成熟系统必备的模块。
其次就是对MD5算法偏移了。由于MD5算法是公开的,那就意味着别人可以利用相同的算法针对你的加密值不断地进行计算。为了避免这个问题,我们可以给算法增加一个偏移量,比如在原始数据上拼接一段数据在进行加密;或者根据原始数据分布范围进行转换,用得到的新值进行MD5计算,这样子被破解的风险就会大大降低。
防止撞库攻击的办法有很多种,最简单的方式就是增加一个图片验证码、自动识别异常IP 整理一个非常严格的库,甚至直接禁止这些IP访问网站,一个一个手工添加肯定很累,程序对程序。
撞库是黑客通过收集互联网已泄露的用户和密码信息,生成对应的字典表,尝试批量登陆其他网站后,得到一系列可以登录的用户。很多用户在不同网站使用的是相同的帐号密码,因此黑客可以通过获取用户在A网站的账户从而尝试登录B网址,这就可以理解为撞库攻击。
2.前台js加密例子
- </pre><pre name="code" class="html"><html>
- <head>
- <meta charset="UTF-8">
- <title>md5</title>
-
- <script type="text/javascript">
- $(function(){
- $("#submit").bind("onclick",function(){
- //检验是否继续保存cookie
- if($("#checkbox")[0].checked) {
- $("#SAVE_PWD").val("_YES");
- }
- else {
- $("#SAVE_PWD").val("_NO");
- }
- //加密
- md5PWD();
- //提交
- $("#loginForm").submit();
- });
-
- //获取cookie
- function checkCookie() {
- var name = "userNbr=";
- var pwd = "userPwd=";
- var ca = document.cookie.split(';');
- for(var i=0; i<ca.length; i++) {
- var c = ca[i];
- if (c.indexOf(name) != -1){
- $("#name").val(c.substring(name.length, c.length));
- $("#checkbox")[0].checked = "checked";
- }
- else if(c.indexOf(pwd) != -1) {
-
-
- $("#PWD").val(c.substring(pwd.length+1, c.length));
- $("#password").val("默认密码");
- }
- }
- }
- checkCookie();
- //对密码进行md5加密,赋给hidden
- function md5PWD(){
- if($("#password").val()=="默认密码"){
- return;
- }
- var md5PWD = $("#password").val();
- $("#PWD").val(hex_md5(md5PWD)) ;//不同的md5.js调用的方法可能不同
- }
-
-
- });
-
- </script>
- </head>
- <body>
- <form action="/LoginController" method="post">
-
- 姓名:<input type="text" name="name" id="name" placeholder="姓名">
- 密码:<input type="password" name="password" id="password" placeholder="密码">
- <input type="hidden" id="PWD">
- <input type="submit" id="submit" value="提交">
- 记住密码:<input type="checkbox" id="checkbox">
- <input type="hidden" id="SAVE_PWD">
- </form>
- </body>
- </html>
loginController 代码片段:
- String setCookie = request.getParameter("SAVE_PWD");
- if ("_YES".equals(setCookie)) {
-
- Cookie cookieName = new Cookie("userNbr", userNbr);
- cookieName.setMaxAge(7 * 24 * 60 * 60 * 1000);
- response.addCookie(cookieName);
- Cookie cookiePwd = new Cookie("userPwd", pwd);
- cookiePwd.setMaxAge(7 * 24 * 60 * 60 * 1000);
- response.addCookie(cookiePwd);
- }
- else {
- Cookie[] cookies = request.getCookies();
- for (int i = 0; i < cookies.length; i++) {
- if ("userNbr".equals(cookies[i].getName()) || "userPwd".equals(cookies[i].getName())) {
- cookies[i].setMaxAge(0);
- response.addCookie(cookies[i]);
- }
- }
- }
3.后台加密例子
package util;
import org.apache.commons.codec.EncoderException;
import java.security.MessageDigest;
/**
* Created by Vivi on 2017/5/12.
*/
public class EncodeUtil {
public String MD5Util(String data) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
char[] chars = data.toCharArray();
byte[] bytes = new byte[chars.length];
for (int i = 0; i < chars.length; i++) {
bytes[i] = (byte) chars[i];
}
byte[] md5byte = md5.digest(bytes);
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < md5byte.length; i++) {
int val = ((int) md5byte[i]) & 0xff;
if (val < 16) {
stringBuffer.append("0");
} else {
stringBuffer.append(Integer.toHexString(val));
}
}
return stringBuffer.toString();
}
public static void main(String args[]) {
EncodeUtil util = new EncodeUtil();
String s = new String("123456");
System.out.println("原始:" + s);
System.out.println("MD5后:" + util.MD5Util(s));
}
}