zoukankan      html  css  js  c++  java
  • 我对shiro的初步认识

    package com.shiro;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    
    /**
     * @since 0.9 RC2
     */
    public class HelloShiro {
    
        private static final transient Logger log = LoggerFactory.getLogger(HelloShiro.class);
    
    
        public static void main(String[] args) {
    
            //创建一个最简单的方法与配置Shiro SecurityManager
            //服务器、用户、角色和权限是使用简单的INI配置。
            //我们会做,通过使用一个工厂能摄取。ini文件和
            //返回一个SecurityManager实例:
            
            //使用shiro。ini文件在类路径的根
            //(文件:和url前缀负载分别从文件和url):
            //1根据配置文件获取一个shiro的的工厂类
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            //2在工厂类中获取shiro的安全管理器
            SecurityManager securityManager = factory.getInstance();
            //3把securityManager放入SecurityUtils中
            SecurityUtils.setSecurityManager(securityManager);
            //4使用SecurityUtils获取当前登录的用户
            Subject currentUser = SecurityUtils.getSubject();
            //5获取当前用户的会话状态 shiro内置的session
            Session session = currentUser.getSession();
            
            //可自行放入一些属性到session里,然后根据自己的业务逻辑进行处理
            session.setAttribute("someKey", "aValue");
            String value = (String) session.getAttribute("someKey");
            if (value.equals("aValue")) {
                log.info("Retrieved the correct value! [" + value + "]");
            }
            //6判断当前用户是否已验证身份
            if (!currentUser.isAuthenticated()) {
                System.out.println("当前用户没有登录---->");
                //7模拟创建一个登录令牌
                UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
                token.setRememberMe(true);
                try {
                    //8进行登录操作
                    //登录流程
                    //currentUser.login(token);--->调用了securityManager.login(this, token)方法
                    //---securityManager的login方法首先调用AuthenticatingSecurityManager的authenticate(AuthenticationToken token)方法
                    //---然后AuthenticatingSecurityManager的authenticate方法调用了ModularRealmAuthenticator的doAuthenticate(AuthenticationToken authenticationToken)
                    //---然后ModularRealmAuthenticator的doAuthenticate方法获取配置文件的的realm,如果配置文件没有定义realm,则默认使用SimpleAccountRealm
                    //--,若配置文件配置了多个realm,则遍历这些realm,并一一调用realm里的getAuthenticationInfo方法来获取AuthenticationInfo(身份验证信息)验证当前登录用户
                    //---从以上流程说明,我们可以通过自定多个realm,然后覆盖getAuthenticationInfo方法,从而达到自定义验证身份的方法
                    currentUser.login(token);
                    //Principal因为是object类型,所以我们在实际业务中可以自己扩展这个类
                    System.out.println("用户已登录---->  用户名:"+currentUser.getPrincipal().toString());
                } catch (UnknownAccountException uae) {
                    log.info("There is no user with username of " + token.getPrincipal());
                } catch (IncorrectCredentialsException ice) {
                    log.info("Password for account " + token.getPrincipal() + " was incorrect!");
                } catch (LockedAccountException lae) {
                    log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                            "Please contact your administrator to unlock it.");
                }
                catch (AuthenticationException ae) {
                }
            }
    
            //9判断当前登录用户的角色---
            //从源代码可以看出,currentUser.hasRole("schwartz")---调用了securityManager.hasRole(getPrincipals(), roleIdentifier)的方法
            //再然后调用了AuthorizingRealm的hasRole(PrincipalCollection principal, String roleIdentifier)方法,
            //而AuthorizingRealm的hasRole方法会先使用getAvailableAuthorizationCache()在缓存里获取AuthorizationInfo,如果缓存里没有AuthorizationInfo
            //则默认的子类SimpleAccountRealm里获取的doGetAuthorizationInfo的方法里AuthorizationInfo(授权信息),而子类SimpleAccountRealm会在 factory.getInstance();时就把用户和角色放入一个map中,
            //也就是说我们可以通过自定义AuthorizingRealm然后覆盖doGetAuthorizationInfo方法来实现我们的自定义验证授权信息
            if (currentUser.hasRole("schwartz")) {
                log.info("May the Schwartz be with you!");
            } else {
                log.info("Hello, mere mortal.");
            }
    
            //test a typed permission (not instance-level)
            //10权限验证
            //从源代码可以看出currentUser.isPermitted("lightsaber:weild")---调用了securityManager.isPermitted(getPrincipals(), permission),
            //----然后调用了AuthorizingRealm的isPermitted(PrincipalCollection principals, String permission),该方法里获取默认的permissionResolver,就是权限字符的解析器
            //---然后调用了AuthorizingRealm。getAuthorizationInfo(),首先在缓存里获取AuthorizationInfo,如果没有,再从子类的SimpleAccountRealm的 doGetAuthorizationInfo去获取AuthorizationInfo
            //----也就是说,我们可以通过AuthorizingRealm类,然后实现doGetAuthenticationInfo方法,从而实现自己业务逻辑的权限验证
            if (currentUser.isPermitted("lightsaber:weild")) {
                log.info("You may use a lightsaber ring.  Use it wisely.");
            } else {
                log.info("Sorry, lightsaber rings are for schwartz masters only.");
            }
    
            //a (very powerful) Instance Level permission:
            if (currentUser.isPermitted("winnebago:drive:eagle5")) {
                log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                        "Here are the keys - have fun!");
            } else {
                log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
            }
    
            //all done - log out!
            currentUser.logout();
            System.exit(0);
        }
    }
  • 相关阅读:
    Ceph实验室:第六课:Ceph运维之横向扩展
    Ceph实验室:第五课:Ceph运维之换盘
    百度2014软件开发工程师笔试题详解 (转)
    阿里巴巴2014笔试题详解(9月22北京)(转)
    阿里巴巴2014秋季校园招聘-软件研发工程师笔试题详解(转)
    腾讯的2014年校招的软开笔试题(转)
    typedef与define区别
    java流总结(转)
    java 流 复制,重命名,删除目录
    java 流 读
  • 原文地址:https://www.cnblogs.com/jeremy-blog/p/5037637.html
Copyright © 2011-2022 走看看