美文网首页
shiro的工作原理

shiro的工作原理

作者: 晚安多巴胺 | 来源:发表于2017-11-30 19:09 被阅读0次

    简述:用户通过subject登陆,形成一个UsernamePasswordToken,令牌,在域realm里完成认证、授权,成功后加入缓存。(realm可以写、也可以用默认的,也可以写很多个域)

    image

    快速入门

    登陆顺序

    1、获取登录凭证

    //1 创建安全管理器
    SecurityManager manager = new IniSecurityManagerFactory("classpath:shiro.ini").getInstance();
    //2 绑定SecurityManager到SecurityUtils
    SecurityUtils.setSecurityManager(manager);
    //3 封装用户名和密码成为一个登录令牌(通行证)
    UsernamePasswordToken token=new UsernamePasswordToken("用户名","密码");
    

    2、提交凭证

    //4 登录校验
    Subject subject = SecurityUtils.getSubject();//获取用户实体(例如从数据库,或者ini配置文件)
    

    3、处理登录结果

    try {
        subject.login(token);
    } catch ( UnknownAccountException uae ) { 
    } catch ( IncorrectCredentialsException ice ) { 
    } catch ( LockedAccountException lae ) { 
    } catch ( ExcessiveAttemptsException eae ) { 
    } 
    } catch ( AuthenticationException ae ) {
    }
    

    1、登录

    SecurityManager manager = new IniSecurityManagerFactory("classpath:shiro.ini").getInstance();
    SecurityUtils.setSecurityManager(manager);
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token=new UsernamePasswordToken("用户名","密码");
    subject.login(token);
     token.setRememberMe(true);//记住我,必须使用user过滤器(登陆或记住我),这里不能用authc(登陆)
    

    2、实际身份认证

    subject委托给securityManager,调用securityManager.login(token)

    3、认证

    SecurityManager接收令牌并简单地委托给realm

    4、认证策略

    如果有多个Realm身份认证,通过认证策略来决定如何认证

    5、Realm认证

    realm中有两个方法,这里是最终提供认证与授权的逻辑的地方

      protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            String username= (String) principalCollection.getPrimaryPrincipal();
            //根据username取userId
            Long id = service.selectId(username);
            //根据userID取roleId
            List<Long> rid = userRoleService.selectId(id);
            //根据rid取role
            Set<String>roleNamelist=new HashSet<String>();
            //根据rid取resourceId
            List<Long> reid=new ArrayList<Long>();
            for (Long r:rid) {
                Role role = roleService.selectById(r);
                roleNamelist.add(role.getName());
                List<Long> reid1 = roleResourceService.selectId(r);
                for (Long rei: reid1) {
                    reid.add(rei);
                }
    
            }
            //根据resourceID取resourceUrl
            Set<String> setUrl=new HashSet<String>();
            for (Long reid2:reid) {
                String s = resourceService.selectUrlById(reid2);
                if (s!=null){
                    setUrl.add(s);
                }
    
            }
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            info.setRoles(roleNamelist);//添加角色
            info.addStringPermissions(setUrl);//添加权限
            return info;
        }
    
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            String username= (String) authenticationToken.getPrincipal();
    
            User user = service.selectOne(new EntityWrapper<User>(new User(username)));
    
            return new SimpleAuthenticationInfo(user.getLogin_name(),user.getPassword(), ByteSource.Util.bytes(salt),getName());
    
        }
    }
    
    

    spring-shiro配置模板

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--创建shiroFilter,shiro的核心-->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <!--注入securityManager-->
            <property name="securityManager" ref="securityManager"/>
            <!--如果没有认证,自动跳转到该页面-->
            <property name="loginUrl" value="/login"/>
            <!--过滤链-->
            <property name="filterChainDefinitions">
                <value>
                    /login*=anon
                    /commons/**=anon
                    /front/**=anon
                    /static/**=anon
                    /** = user<!--authc要登陆才能用,user只要登录过就可以-->
                </value>
            </property>
        </bean>
    
        <!--配置WebSecurityManager-->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <!--注入自定义的realm-->
            <property name="realm" ref="userRealm"/>
            <!--缓存-->
            <property name="cacheManager" ref="cacheManager"/>
        </bean>
    
        <!--自定义reelm,用来认证和授权-->
        <bean class="com.study.shiro.UserRealm" id="userRealm">
            <property name="credentialsMatcher" ref="credentialsMatcher"/>
            <property name="authenticationCachingEnabled" value="true"/>
            <property name="authenticationCacheName" value="authenticationCache"/>
            <property name="authorizationCacheName" value="authorizationCache"/>
        </bean>
    
        <!--凭证匹配器,用来解密md5-->
        <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher" id="credentialsMatcher">
            <property name="hashAlgorithmName" value="md5"/>
        </bean>
    
        <!--生命周期-->
        <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
        <!--换村-->
        <bean class="org.apache.shiro.cache.ehcache.EhCacheManager" id="cacheManager">
            <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
        </bean>
        <bean class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager" id="sessionManager">
            <property name="sessionDAO" ref="sessionDAO"/>
            <!--设置全局会话超时时间 -->
            <property name="globalSessionTimeout" value="#{30 * 60 * 1000}"/>
            <!--URL上带sessionID 默认为true-->
            <property name="sessionValidationSchedulerEnabled" value="false"/>
        </bean>
        <bean class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO" id="sessionDAO">
            <property name="activeSessionsCacheName" value="activeSessionCache"/>
        </bean>
    </beans>
    

    在webxml里的配置

    <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
            <init-param>
                <param-name>targetFilterLifecycle</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>shiroFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    

    相关文章

      网友评论

          本文标题:shiro的工作原理

          本文链接:https://www.haomeiwen.com/subject/kdjvbxtx.html