通常需要对密码 进行散列,常用的有md5、sha,
对md5密码,如果知道散列后的值可以通过穷举算法,得到md5密码对应的明文。
建议对md5进行散列时加salt(盐),进行加密相当 于对原始密码+盐进行散列。(盐就相当于加入一个随机数)
正常使用时散列方法:
在程序中对原始密码+盐进行散列,将散列值存储到数据库中,并且还要将盐也要存储在数据库中。
如果进行密码对比时,使用相同 方法,将原始密码+盐进行散列,进行比对。
package cn.qlq.authentication; import org.apache.shiro.crypto.hash.Md5Hash; import org.apache.shiro.crypto.hash.SimpleHash; /** * 测试MD5算法 * @author: qlq * @date : 2017年7月28日下午9:31:45 */ public class MD5Test { public static void main(String[] args) { //原始 密码 String source = "111111"; //盐 String salt = "qwerty"; //散列次数 int hashIterations = 2; //上边散列1次:f3694f162729b7d0254c6e40260bf15c //上边散列2次:36f2dfa24d0a9fa97276abbe13e596fc //构造方法中: //第一个参数:明文,原始密码 //第二个参数:盐,通过使用随机数 //第三个参数:散列的次数,比如散列两次,相当 于md5(md5(‘‘)) Md5Hash md5Hash = new Md5Hash(source, salt, hashIterations); String password_md5 = md5Hash.toString(); System.out.println(password_md5); // 第二种方法 //第一个参数:散列算法 SimpleHash simpleHash = new SimpleHash("md5", source, salt, hashIterations); System.out.println(simpleHash.toString()); } }
--------------------------------------------------------------------------------------- 自定义realm支持散列算法------------------------------------------------------------------------------------------------------------------
package cn.qlq.realm; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; /** * 自定义realm实现MD5散列算法加密 * @author: qlq * @date : 2017年7月28日下午9:33:14 */ public class CustomRealmMd5 extends AuthorizingRealm { // 设置realm的名称 @Override public void setName(String name) { super.setName("customRealmMd5"); } // 用于认证 @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // token是用户输入的 // 第一步从token中取出身份信息 String userCode = (String) token.getPrincipal(); // 第二步:根据用户输入的userCode从数据库查询 // .... // 如果查询不到返回null // 数据库中用户账号是zhangsansan /* * if(!userCode.equals("zhangsansan")){// return null; } */ // 模拟从数据库查询到密码,散列值 String password = "f3694f162729b7d0254c6e40260bf15c"; // 从数据库获取salt String salt = "qwerty"; //上边散列值和盐对应的明文:111111 // 如果查询到返回认证信息AuthenticationInfo SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( userCode, password, ByteSource.Util.bytes(salt), this.getName()); return simpleAuthenticationInfo; } // 用于授权 @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { // TODO Auto-generated method stub return null; } }
测试:
// 自定义realm实现散列值匹配 @Test public void testCustomRealmMd5() { // 创建securityManager工厂,通过ini配置文件创建securityManager工厂 Factory<SecurityManager> factory = new IniSecurityManagerFactory( "classpath:shiro-realm-md5.ini"); // 创建SecurityManager SecurityManager securityManager = factory.getInstance(); // 将securityManager设置当前的运行环境中 SecurityUtils.setSecurityManager(securityManager); // 从SecurityUtils里边创建一个subject Subject subject = SecurityUtils.getSubject(); // 在认证提交前准备token(令牌) // 这里的账号和密码 将来是由用户输入进去 UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "111111"); try { // 执行认证提交 subject.login(token); } catch (AuthenticationException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 是否认证通过 boolean isAuthenticated = subject.isAuthenticated(); System.out.println("是否认证通过:" + isAuthenticated); }
原文:http://www.cnblogs.com/qlqwjy/p/7252780.html