zoukankan      html  css  js  c++  java
  • 4、散列算法&凭证配置

    散列算法

    散列算法概述

    散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐)。

    比如加密密码“admin”,产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,这个散列值在一些md5解密网站很容易得到密码“admin”,即如果直接对密码进行散列相对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,这些干扰数据就是salt,如用户名和ID(即盐)。这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。

    MD5算法

    盐(Salt):在密码学中,指在散列之前将散列内容的任意固定位置插入特定的字符串。

    散列次数:就是将散列内容进行加密的次数,如使用MD5(MD5(password))可以表示散列2次。

    package com.coydone.test;
    
    import org.apache.shiro.crypto.hash.Md5Hash;
    
    public class MD5Test {
        public static void md5(){
            String password = "123456";
            //使用MD5、不加盐、散列一次进行加密
            String p2 = new Md5Hash(password).toString();
            System.out.println(p2);
            //参数:1 加密的原文、2 盐、3 散列次数
            //Md5Hash(Object source, Object salt, int hashIterations)
            String p3 = new Md5Hash(password,"admin" ,3).toString();
            System.out.println(p3);
        }
    
        public static void main(String[] args) {
            md5();
        }
    }
    

    凭证配置

    在自定义Realm中使用散列

    1、修改UserRealm将密码改为密文。

    package com.coydone.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;
    
    public class UserRealm extends AuthorizingRealm {
        //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            //1、得到身份
            String username = token.getPrincipal().toString();
            //得到凭证
            //String password = token.getCredentials().toString();
            
            //2,根据用户名到数据库中取出用户信息  如果查询不到 返回null  可以使用service来查
    
            //假如从数据库中获取密码 使用md5加密的字符串,盐 admin,散列3次
            String password = "9aa75c4d70930277f59d117ce19188b0";
    
            //3,返回认证信息
            /**
             * 参数1:可以传到任意对象,如果登录成功,会调用doGetAuthorizationInfo去授权
             * 参数2:从数据库里面查询出来的密码
             * 参数3:盐
             * 参数4:当前类名
             */
            ByteSource salt = ByteSource.Util.bytes("admin");
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password,salt,this.getName());
            return info;
        }
    
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            return null;
        }
    }
    

    2、修改shiro.ini文件配置散列次数。

    # 作全局配置
    [main]
    # 定义凭证匹配器
    credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
    # 散列算法
    credentialsMatcher.hashAlgorithmName=md5
    # 散列次数
    credentialsMatcher.hashIterations=3
    
    # 创建UserRealm的对象
    userRealm=com.coydone.realm.UserRealm
    
    # 将凭证匹配器设置到realm
    userRealm.credentialsMatcher=$credentialsMatcher
    
    # 创建默认的安全管理器
    securityManager=org.apache.shiro.mgt.DefaultSecurityManager
    # 把userRealm给安全管理器
    securityManager.realms=$userRealm
    

    3、测试

    package com.coydone.test;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    
    public class AuthUserTeat {
        public static void main(String[] args) {
            //1、接收用户名和密码
            String username = "zhangsan";
            String password = "123456";
    
            //2、把用户名和密码封装
            UsernamePasswordToken token = new UsernamePasswordToken(username,password);
    
            //3、创建安全管理器的工厂
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    
            //4、从Factory中得到安全管理器
            SecurityManager securityManager = factory.getInstance();
    
            //5、把securityManager和Subject绑定到当前线程
            SecurityUtils.setSecurityManager(securityManager);
    
            //6、从SecurityUtils中得到subject
            Subject subject = SecurityUtils.getSubject();
    
            //7、去认证
            try {
                subject.login(token);
                System.out.println("认证通过");
            } catch (AuthenticationException e) {
                System.out.println("用户名或密码不正确");
            }
            /*
            catch (IncorrectCredentialsException e) {
                System.out.println("密码不正确");
            } catch (UnknownAccountException e) {
                System.out.println("用户名不存在");
            }
             */
    
            //8、查看认证状态
            System.out.println("认证状态:"+subject.isAuthenticated());
    
            //9、退出
            subject.logout();
            System.out.println("认证状态:"+subject.isAuthenticated());
        }
    }
    
    coydone的博客
  • 相关阅读:
    第六周
    第五周
    第四周
    第二周学习记录
    实验一 Linux初步认识
    java实验四
    java实验三
    为什么无密码认证能够有效
    关于父元素,子元素,同级元素的DOM操作技巧
    高效设计构建软件的十三条建议
  • 原文地址:https://www.cnblogs.com/coydone/p/13779968.html
Copyright © 2011-2022 走看看