zoukankan      html  css  js  c++  java
  • Shiro入门学习之散列算法与凭证配置(六)

    一、散列算法概述

      散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等,一般进行散列时最好提供一个salt(“盐”),什么意思?举个栗子:加密密码“admin”,产生的散列值是21232f297a57a5a743894a0e4a801fc3,可以到一些md5解密网站(注:并不是真正解密,而是通过穷举法不断尝试)很容易通过散列值得到密码(admin),即如果直接对密码进行散列相对来说破解更容易,此时我们加入一些只有系统知道的干扰数据,如用户名和ID(盐);这样散列对象是“密码+用户名+ID”,这样生成的散列值来说更难破解。

    二、凭证配置

      鄙人能力有限,不会叙述其是怎么实现的,有能力的可以自己去百度了。。这里仅仅记录我学习Shiro过程中通过MD5散列算法对密码进行加密,这也是Shiro框架的一部分。

    1、新建module,添加如下pom依赖

    <properties>
            <shiro.version>1.4.1</shiro.version>
            <loggingg.version>1.2</loggingg.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>${shiro.version}</version>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>${loggingg.version}</version>
            </dependency>
        </dependencies>

    2、配置凭证

    (1)第一种方式:在自定义Realm的构造方法中设置匹配器

     实现如下:

     关键代码如下:

    public class UserRealm extends AuthorizingRealm {
        private UserService userService = new UserServiceImpl();
        private RoleService roleService = new RoleServiceImpl();
        private PermissionService permissionService = new PermissionServiceImpl();
    
        public UserRealm()
        {
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            //指定加密算法
            hashedCredentialsMatcher.setHashAlgorithmName("md5");
            //指定散列次数
            hashedCredentialsMatcher.setHashIterations(2);
            //这里没有设置salt(盐)的api,为什么这么设计?因为一般salt(盐)存储在数据库
            setCredentialsMatcher(hashedCredentialsMatcher);
        }
        /**
         * 做认证
         *
         * @param token
         * @return
         * @throws AuthenticationException
         */
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String username1 = token.getPrincipal().toString();
            User user1 = userService.queryUserByUserName(username1);
            if (user1 != null) {
                List<String> roles1 = roleService.queryRoleByUserName(username1);
                List<String> permissions1 = permissionService.queryPermissionByUserName(username1);
                ActivityUser activityUser1 = new ActivityUser(user1, roles1, permissions1);
                System.out.println();
                //参数1:可以传任意对象的|参数2:数据库中的用户密码|参数3:当前类名
                //SimpleAuthenticationInfo info1 = new SimpleAuthenticationInfo(activityUser1, user1.getPwd(), this.getName());
                ByteSource byteSource = ByteSource.Util.bytes("北京");
                SimpleAuthenticationInfo info1 = new SimpleAuthenticationInfo(activityUser1, user1.getPwd(), byteSource, this.getName());
                return info1;
            } else {
                return null;
            }
        }
    
        //授权方法
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            System.out.println("doGetAuthorizationInfo被回调了!");
            //
            Object primaryPrincipal = principal.getPrimaryPrincipal();
            System.out.println(primaryPrincipal);
    
            ActivityUser activityUser = (ActivityUser) principal.getPrimaryPrincipal();
            List<String> roles = activityUser.getRoles();
            if (roles != null && roles.size() > 0) {
                info.addRoles(roles);
            }
            List<String> permissins = activityUser.getPermissins();
            if (permissins!=null&&permissins.size()>0)
            {
                info.addStringPermissions(permissins);
            }
            //判断如果是超级管理员
            //info.addStringPermission("*:*");
            return info;
        }
    }
    关键代码

     (2)第2种方式:shiro.ini设置凭证匹配器

     (3)第3种方式:代码中设置凭证匹配器

     关键代码如下:

    public class TestAuthorizationRealm
    {
        public static void main(String[] args)
        {
            //1.模拟前台传递的用户名和密码
            String username = "zhangsan";
            String password = "123456";
            //2.创建安全管理器的工厂
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            //3.通过安全管理器工厂获取安全管理器
            DefaultSecurityManager securityManager = (DefaultSecurityManager)factory.getInstance();
            //4.创建自定义的Realm
            UserRealm userRealm = new UserRealm();
            //4.1设置凭证匹配器
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            //4.2指定加密算法
            hashedCredentialsMatcher.setHashAlgorithmName("md5");
            //4.3指定散列次数
            hashedCredentialsMatcher.setHashIterations(2);
            //4.4这里没有设置salt(盐)的api,为什么这么设计?因为一般salt(盐)存储在数据库
            userRealm.setCredentialsMatcher(hashedCredentialsMatcher);
            //5.设置自定义的Realm
            securityManager.setRealm(userRealm);
            //6.将安全管理器绑定到当前运行环境
            SecurityUtils.setSecurityManager(securityManager);
            //7.从当前环境中获取Subject主体
            Subject subject1 = SecurityUtils.getSubject();
            //8.调用主体的登录方法
            try
            {
                subject1.login(new UsernamePasswordToken(username,password));
                System.out.println("登录成功~");
    
    //            Object principal = subject1.getPrincipal();
    //            System.out.println(principal);
    
            } catch (IncorrectCredentialsException e) {
                System.out.println("密码不正确");
            }catch (UnknownAccountException e) {
                System.out.println("用户名不存在");
            }
    
            boolean role1 = subject1.hasRole("role1");
            boolean role2 = subject1.hasRole("role1");
            System.out.println(role1);
    
            boolean permitted = subject1.isPermitted("user:add");
            System.out.println(permitted);
        }
    }
    关键代码

     三、总结

    1、以前我们是拿用户名和密码去匹配数据库中有没有User对象,而在Shiro中是通过用户名查询User对象,将前台获取到的明文进行加密(md5、sha等等)与数据库中的密文密码作比对

    2、以上3种设置凭证匹配器本质都是一样的

  • 相关阅读:
    bzoj3272 Zgg吃东西
    bzoj3894 文理分科
    poj1149 PIGS
    poj1637 Sightseeing tour
    [Wc2007]剪刀石头布
    poj2396 Budget
    [NOI2017]游戏
    CF666E Forensic Examination
    bzoj4889 [Tjoi2017]不勤劳的图书管理员
    CF587F Duff is Mad
  • 原文地址:https://www.cnblogs.com/rmxd/p/11769251.html
Copyright © 2011-2022 走看看