乐趣区

前后端日常使用前后端两次MD5加密

MD5 加密设计

前端后端分别进行一次 md5+salt 加密

前端加密

为了防止密码明文在 http 上传输,则需要在前端进行一次 md5+salt 加密

  • 使用JQuery md5

前端 JQuery md5 工具:https://github.com/emn178/js-md5

  • 在前端 js 中声明一个固定盐 salt
//salt
var g_passsword_salt="ewn576ifa12";
  • 登录 js 方法中加密调用ajax

这里使用layer Web 组件,进行 ajax 消息弹窗

function doLogin(){var inputPass = $("#password").val();
    var salt = g_passsword_salt;
    // 使用盐中 5 位组合 md5 加密
    var str = ""+salt.charAt(0) + salt.charAt(2) + salt.charAt(5) + inputPass + salt.charAt(7) + salt.charAt(8);
    var password = md5(str);
    // 使用第一次加密的密码进行 ajax 传输
    $.ajax({
        url: "/login/do_login",
        type: "POST",
        data:{mobile:$("#mobile").val(),
            password: password
        },
        // 成功回调函数
        success:function(data){layer.closeAll();
            if(data.code == 2000){layer.msg("成功");
                window.location.href="/goods/to_list";
            }else{layer.msg(data.msg);
            }
        },
        // 失败回调函数
        error:function(){layer.closeAll();
        }
    });
}

后端加密存储

后端将拿到第一次 md5 加密的结果,这个密码就是表单提交上来的密码,我们需要在后端编写第二道 md5 加密方式来加密表单传来的密码后再与数据库存储的两次 md5 加密的密码进行比较,相同才能登陆成功

  • 第二次加密作用:因为第一次前端加密的密码有可能被窃取的,也可能解析我们的 js 看到我们前端加密方式,可以直接得到明文密码,所以我们需要第二次后端加密再存储,这样即使前端密码被拿到了后端的也不符合。

我们将后端使用同样的方式 (也可以用不同的方式) 再次加密,盐值 salt 需要相等,用于注册时,后端进行计算出与前端第一次加密匹配的密码。

  • 依赖:Apache-commons-codec
<dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.9</version>
        </dependency>
  • MD5Util 类
public class MD5Util {public static String md5(String t){return DigestUtils.md5Hex(t);
    }

    private static final String salt = "ewn576ifa12";
// 前端输入的密码到表单提交的密码(第一次加密) 用于校验前端传入的密码与该方法返回的密码是否相等
    public static String inputPassToFormPass(String pass){String s = "" + salt.charAt(0) + salt.charAt(2) + salt.charAt(5) + pass + salt.charAt(7) + salt.charAt(8);
        return md5(s);
    }
// 表单提交的密码 (第一次加密的密码) 到数据库存储的密码(第二次加密)
    public static String formPassToDb(String formPass,String salt){String s = "" + salt.charAt(0) + salt.charAt(2) + salt.charAt(5) + formPass + salt.charAt(7) + salt.charAt(8);
        return md5(s);
    }
// 前端输入的明文密码到数据库存储的密码 可用于注册
    public static String inputPassToDbPass(String input,String salt){String form = inputPassToFormPass(input);
        return formPassToDb(form,salt);
    }
}
  • 登录业务代码
public boolean login(HttpServletResponse response,String mobile, String formPass) {
    // 根据手机号获取 User 用户对象
        User user = UserMapper.getById(Long.parseLong(mobile));
        if(user==null){throw new GlobalException(ErrorCodeEnum.MOBILE_NOT_EXIST);// 抛出自定义异常
        }
        String dbPass = user.getPassword();// 获取数据库的第二次加密的密码
        String dbSalt = user.getSalt();// 获取后端存储的盐
        String calPass = MD5Util.formPassToDb(formPass,dbSalt);// 根据前端表单传来的密码计算出第二次加密结果
        if(!calPass.equals(dbPass)){// 如果不相等
            log.error("{}登录密码错误",mobile);
            throw new GlobalException(ErrorCodeEnum.LOGIN_FAIL);
        }
        return true;
    }
退出移动版