一.陈述一下工作流程:

1.根据已有的密码字符串去生成一个密码+盐字符串,可以将盐的加密字符串也存放在数据库(看需求),

2.验证时将提交的密码字符串进行同样的加密再从数据库中取得已有的盐进行组合密码+盐的字符串和已有的进行验证

package com.mi.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays; public class Md5SaltTool { private static final String HEX_NUMS_STR="0123456789ABCDEF";
private static final Integer SALT_LENGTH = 12; /**
* 将16进制字符串转换成字节数组
* @param hex
* @return
*/
public static byte[] hexStringToByte(String hex) {
int len = (hex.length() / 2);
byte[] result = new byte[len];
char[] hexChars = hex.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4
| HEX_NUMS_STR.indexOf(hexChars[pos + 1]));
}
return result;
} /**
* 将指定byte数组转换成16进制字符串
* @param b
* @return
*/
public static String byteToHexString(byte[] b) {
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
hexString.append(hex.toUpperCase());
}
return hexString.toString();
} /**
* 验证口令是否合法
* @param password
* @param passwordInDb
* @return
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
public static boolean validPassword(String password, String passwordInDb)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
//将16进制字符串格式口令转换成字节数组
byte[] pwdInDb = hexStringToByte(passwordInDb);
//声明盐变量
byte[] salt = new byte[SALT_LENGTH];
//将盐从数据库中保存的口令字节数组中提取出来
System.arraycopy(pwdInDb, 0, salt, 0, SALT_LENGTH);
//创建消息摘要对象
MessageDigest md = MessageDigest.getInstance("MD5");
//将盐数据传入消息摘要对象
md.update(salt);
//将口令的数据传给消息摘要对象
md.update(password.getBytes("UTF-8"));
//生成输入口令的消息摘要
byte[] digest = md.digest();
//声明一个保存数据库中口令消息摘要的变量
byte[] digestInDb = new byte[pwdInDb.length - SALT_LENGTH];
//取得数据库中口令的消息摘要
System.arraycopy(pwdInDb, SALT_LENGTH, digestInDb, 0, digestInDb.length);
//比较根据输入口令生成的消息摘要和数据库中消息摘要是否相同
if (Arrays.equals(digest, digestInDb)) {
//口令正确返回口令匹配消息
return true;
} else {
//口令不正确返回口令不匹配消息
return false;
}
} /**
* 获得加密后的16进制形式口令
* @param password
* @return
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
public static String getEncryptedPwd(String password)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
//声明加密后的口令数组变量
byte[] pwd = null;
//随机数生成器
SecureRandom random = new SecureRandom();
//声明盐数组变量 12
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);
for(int i=0;i<pwd.length;i++){
System.out.print(pwd[i]);
}
//将字节数组格式加密后的口令转化为16进制字符串格式的口令
return byteToHexString(pwd);
}
}

测试类如下:

package com.mi.util;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map; public class Md5SaltTest { private static Map users = new HashMap(); public static void main(String[] args){
String userName = "zyg";
String password = "123";
registerUser(userName,password); userName = "changong";
password = "456";
registerUser(userName,password); String loginUserId = "zyg";
String pwd = "1232";
try {
if(loginValid(loginUserId,pwd)){
System.out.println("欢迎登陆!!!");
}else{
System.out.println("口令错误,请重新输入!!!");
}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} /**
* 注册用户
*
* @param userName
* @param password
*/
public static void registerUser(String userName,String password){
String encryptedPwd = null;
try {
encryptedPwd = Md5SaltTool.getEncryptedPwd(password);
users.put(userName, encryptedPwd); } catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} /**
* 验证登陆
*
* @param userName
* @param password
* @return
* @throws UnsupportedEncodingException
* @throws NoSuchAlgorithmException
*/
public static boolean loginValid(String userName,String password)
throws NoSuchAlgorithmException, UnsupportedEncodingException{
/*String loginUserId = "zyg";
String pwd = "1232";*/
String pwdInDb = (String)users.get(userName);
if(null!=pwdInDb){ // 该用户存在
return Md5SaltTool.validPassword(password, pwdInDb);
}else{
System.out.println("不存在该用户!!!");
return false;
}
}
}

Java关于md5+salt盐加密验证的更多相关文章

  1. 关于MD5+salt盐加密

    MD5+salt 最近浏览浏览一些帖子时,发现曾经引以为傲的md5加密算法,虽然是无法解密的算法,但是现在可以通过FELHELP(谷歌浏览器插件)或者一些字典可以套出来,.但是当md5+salt值时, ...

  2. Java使用MD5加盐进行加密

    Java使用MD5加盐进行加密    我使用的方法是导入了md5.jar包,就不需要再自己写MD5的加密算法了,直接调用方法即可 点击下载md5包 import com.ndktools.javamd ...

  3. md5加密,md5加盐加密和解密

    package com.java.test; import java.security.MessageDigest; import java.security.SecureRandom; import ...

  4. 一种简单的md5加盐加密的方法(防止彩虹表撞库)

    md5加密(或者说摘要算法)大家都很熟悉了 就不解释了 现在很多数据库设计都喜欢用单向加密的方式保存密码,验证时对提交的密码再次加密之后做密文对比 /// <summary> 使用MD5加 ...

  5. MD5 加盐加密

    一.概述 MD5(Message Digest  Algorithm 5),是一种散列算法,是不可逆的,即通过md5加密之后没办法得到原文,没有解密算法. 在一般的项目中都会有登录注册功能,最简单的, ...

  6. MD5加盐加密

    package com.chauvet.utils; import java.security.NoSuchAlgorithmException; import java.util.Random; / ...

  7. JAVA通过md5方法进行加密

    import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /* * MD5 算法 * */ ...

  8. shiro入门学习--使用MD5和salt进行加密|练气后期

    写在前面 在上一篇文章<Shiro入门学习---使用自定义Realm完成认证|练气中期>当中,我们学会了使用自定义Realm实现shiro数据源的切换,我们可以切换成从关系数据库如MySQ ...

  9. SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理(上)----筑基中期

    写在前面 通过前几篇文章的学习,我们从大体上了解了shiro关于认证和授权方面的应用.在接下来的文章当中,我将通过一个demo,带领大家搭建一个SpringBoot整合Shiro的一个项目开发脚手架, ...

随机推荐

  1. IOS启动顺序

    一.UIApplicationMain的执行步骤1.创建一个UIApplication对象,一个程序对应一个UIApplication对象(单例),UIApplication对象是程序的象征2.接下来 ...

  2. VS开发好用的扩展

    VS开发好用的扩展(转) 转自:http://www.haogongju.net/art/1977373 首先为大家介绍一下开发字体,做程序开发,代码可读性,在侧面也能帮助开发提高效率,所以给大家介绍 ...

  3. MyBatis调用存储过程,含有返回结果集、return参数和output参数

    Ibatis是我们经常使用的O/R映射框架,mybats是ibatis被Google收购后重新命名的一个工程,当然也做了大量的升级.而调用存储过程也是一次额C/S架构模式下经常使用的手段,我们知道,i ...

  4. 【android studio】android studio使用过程中,搜集的一些问题

    1.[知乎]在Android Studio中如何将依赖的jar包放在SDK的android.jar前? 在编译原生Contacts应用时需用到非公开的API,需要引入framework等jar包,但在 ...

  5. iOS 导入第三方文件夹时右侧出现问号

    首先,和版本库有关. a代表add,m代表modify,?代表未能识别,通常如果使用git之类的版本控制器,添加文件后没有进行提交,就会出现? 1.遇到引用文件夹为蓝色的情况,是你以为勾了copy项, ...

  6. 使用EXECUTE IMMEDIATE来生成含有绑定变量的SQL

    一个SQL,通过SPM固定它的执行计划,可以通过DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE实现.也可以通地此功能在不修改原SQL的情况下对其加HINT来固定执行计划.D ...

  7. BizTalk开发系列(三十一)配置和使用HTTP适配器

    BizTalk的主机分别进程内主机和独立主机.但由于一直使用的是进程内主机,对于独立主机的认识比较模糊,前不久在做一个BizTalk的项目的时 候,个别系统使用HTTP的方式发布Txt之类的文本的.刚 ...

  8. 数据库---MySQL练习题及答案

    一.            设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...

  9. Suffix array

    A suffix array is a sorted array of all suffixes of a given string. The definition is similar to Suf ...

  10. 【iCore3 双核心板_FPGA】例程一:认识FPGA

    实验指导书及代码包下载: http://pan.baidu.com/s/1kUa05FL iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...