先加载对密码进行MD5加密和比较的基本操作
public class MD5utils {
private static final String HEX_NUMS_STR = "0123456789ABCDEF";
private static final Integer SALT_LENGTH = 12;
// 将16进制字符串转换成字节数组
public static byte[] hexStringToByte(String hex) {
System.out.println("=="+hex);
int len = (hex.length() / 2);
byte[] result = new byte[len];
char[] hexChars = hex.toCharArray();
//每两位数为一个16进制
for (int i = 0; i < len; i++) {
int pos = i * 2;
System.out.println("===="+HEX_NUMS_STR.indexOf(hexChars[pos]));
//把char[]中的数重新转换为16进制的数存入数组
result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4 | HEX_NUMS_STR.indexOf(hexChars[pos + 1]));
}
return result;
}
//字节数组转16进制
public static String byteToHexString(byte[] byt){
StringBuffer hexString = new StringBuffer();
for(int i = 0 ; i<byt.length; i++){
//十进制转换为16进制 &0xFF 是为了把二进制中的负数位变为0,因为0xff在二进制里有8位,做运算结果也只取前8位
String hex = Integer.toHexString(byt[i] & 0xFF);
//两位数的16进制
if(hex.length() == 1){
hex = '0'+hex;
}
hexString.append(hex.toUpperCase());
}
return hexString.toString();
}
//密码比较
public static boolean validPassword(String password , String passwordInDb)
throws NoSuchAlgorithmException, UnsupportedEncodingException{
//数据库中取出的16进制字符串格式
byte[] pwdIn = hexStringToByte(passwordInDb);
// 声明盐变量 作用:为了使相同的密码拥有不同的hash值的一种手段 就是盐化
byte[] salt = new byte[SALT_LENGTH];
// 将盐值从数据库中保存的密码字节数组中提取出来
System.arraycopy(pwdIn, 0, salt, 0, SALT_LENGTH);
// 创建消息摘要对象
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(salt);
// 将密码的数据传给消息摘要对象
md.update(password.getBytes("utf-8"));
//生成输入密码的摘要(hash) 16
byte[] digest = md.digest();
//减去盐值长度获得装hash值的长度
byte[] digestIn = new byte[pwdIn.length - SALT_LENGTH];
//输入的密码除去首部的盐值长度,把加密的输入密码复制出来
System.arraycopy(pwdIn, SALT_LENGTH, digestIn, 0, digestIn.length);
//比较输入密码和数据库密码中hash是否相同
if(Arrays.equals(digest, digestIn)){
return true;
}else{
return false;
}
}
//md5加密方法
public static String getEncryptedPwd(String password)
throws UnsupportedEncodingException, NoSuchAlgorithmException{
byte[] pwd = null;
// 随机数生成器
SecureRandom random = new SecureRandom();
//声明装入盐值的数组
byte[] salt = new byte[SALT_LENGTH];
// 将随机数放入盐变量中
random.nextBytes(salt);
// 声明消息摘要对象
MessageDigest md = null;
// 创建消息摘要
md = MessageDigest.getInstance("MD5");
// 将盐数据传入消息摘要对象
md.update(salt);
// 将口令的数据传给消息摘要对象
md.update(password.getBytes("UTF-8"));
// 获得消息摘要的字节数组
byte[] digest = md.digest();
// 因为要在口令的字节数组中存放盐,所以加上盐的字节长度
pwd = new byte[digest.length + SALT_LENGTH];
// 将盐的字节拷贝到生成的加密口令字节数组的前12个字节,以便在验证口令时取出盐
System.arraycopy(salt, 0, pwd, 0, SALT_LENGTH);
// 将消息摘要拷贝到加密口令字节数组从第13个字节开始的字节
System.arraycopy(digest, 0, pwd, SALT_LENGTH, digest.length);
// 将字节数组格式加密后的口令转化为16进制字符串格式的口令
return byteToHexString(pwd);
}
}
servlet中的注册方法(没存入数据库)
private static Map<String, String> users = new HashMap<String, String>();
public static void registerUser(HttpServletRequest request,HttpServletResponse response){
//获取参数
String userName = request.getParameter("user_name");
String userPwd = request.getParameter("user_pwd");
String encryptePwd = "";
try {
//加密
encryptePwd = MD5utils.getEncryptedPwd(userPwd);
//存入map中
users.put(userName, encryptePwd);
System.out.println("==="+users.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
servlet中的登录比较密码方法
public static void loginValid(HttpServletRequest request,HttpServletResponse response) throws NoSuchAlgorithmException, UnsupportedEncodingException{
//获取参数
String userName = request.getParameter("user_name");
String userPwd = request.getParameter("user_pwd");
//取出map中数据
String pwdInDb =(String) users.get(userName);
if(null!=pwdInDb){
//判断 验证密码 是否和数据库的 密码一致
boolean bool = MD5utils.validPassword(userPwd, pwdInDb);
System.out.println("===>"+bool);
}
}
//需要下载jquery.md5.js
jsp中对密码加密的function
<script type="text/javascript">
function md_register(){
var password = $('#register_pwdId').val();
var pwd = $.md5(password);
$('#userpwdId').val(pwd);
}
function md_login(){
var password = $('#login_pwdId').val();
var pwd = $.md5(password);
$('#login_pwd_id').val(pwd);
}
</script>