• spring 集成 shiro安全框架


    基于xml 配置文件集成

    1. web.xml 文件

    <!-- 配置Shiro安全过滤器 -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <!-- 此类由spring-web 提供 -->
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <!-- 这个参数名在DelegatingFilterProxy中定义 -->
            <param-name>targetBeanName</param-name>
            <!-- 这个值在spring-shiro.xml配置文件中定义 -->
            <param-value>shiroFilterFactory</param-value>
        </init-param>
    </filter>

    <filter-mapping>
      <filter-name>shiroFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>

    shiro 的配置文件

    spring-shiro.xml

           <!-- 配置SecurityManager对象,(Shiro框架核心,负责调用相关组件,实现
           用户身份认证,缓存,会话管理等功能 -->
           <bean id="securityManager"
                       class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
                       <property name="Realm" ref="shiroUserRealm"></property>
           </bean>
           <!-- 配置ShiroFilterFactoryBean对象
           (Shiro中会通过很多过滤器对WEB请求做预处理 ,这些过滤器的创建
           底层设计了一个工厂类-->
           <bean id="shiroFilterFactory" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
                   <!-- 注入securityManager对象 -->
                   <property name="SecurityManager" ref="securityManager"></property>
                   <!-- 配置登录页面 -->
                   <property name="LoginUrl" value="/doLoginUI.do"></property>
                   <!-- 过滤给则(哪些资源允许匿名访问,哪些资源需要授权访问)
                           anon:允许匿名访问    authc需要授权访问 -->
                   <property name="FilterChainDefinitionMap">
                       <map>
                           <entry key="/bower_components/**" value="anon"></entry>
                           <entry key="/build/**" value="anon"></entry>
                           <entry key="/dist/**" value="anon"></entry>
                           <entry key="/plugins/**" value="anon"></entry>
                           <entry key="/doLogin.do" value="anon"></entry>
                  <entry key="/doLogout.do" value="logout"></entry>  //登出操作 <entry key="/**" value="authc"></entry><!-- 必须认证 --> </map> </property> </bean>

    Realm:

    package com.demo.realm;
    
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
    
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.LockedAccountException;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authc.credential.CredentialsMatcher;
    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    
    import com.demo.entity.SysUser;
    import com.demo.mapper.SysUserDao;
    
    
    /**
     * 借助此对象访问用户身份信息,权限信息并对
     * 其进行封装,返回给调用者.
     * 思考?
     * 1)此对象由谁来调用?(认证管理器,授权管理器)
     * @author adminitartor
     */
    @Service
    public class ShiroUserRealm extends AuthorizingRealm {
    
        @Autowired
        private SysUserDao sysUserDao;
        
        //ConcurrentHashMap()在jdk1.5之后推出,在1.8和1.8之后
        //添加了红黑树
        private Map<String, SimpleAuthorizationInfo> authMap=
                new ConcurrentHashMap<String, SimpleAuthorizationInfo>();
        
        /***
         * 完成授权信息的获取以及封装.
         * 此方法何时调用?(执行授权检测时调用)
         * 
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(
                PrincipalCollection principals) {
            System.out.println("realm.doGetAuthorizationInfo");
            //1.获取登陆用户身份信息,(基于登录认证时传递的主身份)
            String username=
            (String)principals.getPrimaryPrincipal();
            //查询缓存中是否有这个
            if(authMap.containsKey(username))
                return authMap.get(username);
            //2.查找用户的权限信息
            List<String> list=//sys:user:update,sys:user:view,....,
            sysUserDao.findUserPermissions(username);
            System.out.println("list="+list);
            //去重去空
            Set<String> permissions=new HashSet<String>();
            for(String permission:list){
                if(!StringUtils.isEmpty(permission)){
                    permissions.add(permission);
                }
            }
            System.out.println("====查询认证信息");
            //3.对权限信息进行封装
            SimpleAuthorizationInfo info=
            new SimpleAuthorizationInfo();
            info.setStringPermissions(permissions);
            authMap.put(username, info);
            return info;
        }
        /**
         * 完成认证信息的获取以及封装
         * 此方法何时调用?(执行登陆认证时调用)
         * @param  
         * 用于接收用户身份以及凭证信息的对象(用户输入的)
         * 
         * @return AuthenticationInfo  
         * 封装了认证信息的对象(从数据库查询到的)
         * 
         * client-->controller-->service-->realm
         */
        @Override
        protected AuthenticationInfo 
        doGetAuthenticationInfo(
                AuthenticationToken token) 
                        throws AuthenticationException {
            System.out.println("进行身份认证");
            //1.获取用户身份信息
            UsernamePasswordToken uToken=
            (UsernamePasswordToken)token;
            String username=uToken.getUsername();
            //String username=token.getPrintcipal();
            //2.基于用户身份查询数据库信息
            SysUser sysUser=
            sysUserDao.findUserByUserName(username);
            if(sysUser==null)
                throw new UnknownAccountException("密码或账号错误");
            if(sysUser.getValid()==0){
                throw new LockedAccountException("用户被锁定");
            }
            //3.对查询结果进行封装.
            //3.1获取用户salt值,并将其转换为一个字节源对象
            ByteSource byteSource=
            ByteSource.Util.bytes(sysUser.getSalt());
            //3.2对用户信息进行封装返回.
            AuthenticationInfo info=
            new SimpleAuthenticationInfo(
                sysUser.getUsername(), //主身份
                sysUser.getPassword(), //已加密的密码
                byteSource,//salt对应的字节源对象
                getName());//realm 的名字
            return info;
        }
        
        
        /**
         * 设置凭证(密码)匹配器
         */
        @Override
        public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
            HashedCredentialsMatcher hMatcher = new HashedCredentialsMatcher();
            //设置加密算法
            hMatcher.setHashAlgorithmName("MD5");
            //设置加密次数
            //hMatcher.setHashIterations(5);
            
            super.setCredentialsMatcher(hMatcher);
        }
    
    }

    认证流程图:

     认证和记住我:

    subject.isAuthenticated()  表示用户进行了身份验证登录的,即使有Subject.login 进行了登录

    subject.isRemembered()  表示用户是通过 记住我 登录的,此时可能不是真正的你(如果你的朋友使用了你的电脑,或者你的Cookie被窃取)在访问的

    两者二选一。即subject.isAuthenticate()==true,则subject.isRemembered()==false,反之一样。

      流程解析:

        当客户端访问服务器时,DelegatingFilterProxy 对象会拦截所有的请求路径,并把它交给ShiroFilterFactoryBean对象处理,ShiroFilterFactoryBean对象中注入了SecurityMananger对象,负责调用相关组件,实现用户身份认证,缓存,会话管理等功能。

        ShiroFilterFactoryBean对象中还配置了FilterChainDefinitionMap这个参数,这个参数其实也相当于一个过滤器,他定义了哪些资源外部可以直接进行访问,哪些资源需要认证之后才能访问。ShiroFilterFactoryBean对象还对LoginUrl这个参数进行了设置,这个参数主要意义为:FilterChainDefinitionMap拦截的请求,直接重定向到LoginUrl这个参数配置的路径进行访问。

  • 相关阅读:
    【奇妙dp】ARC107D Number of Multisets
    【最短路-拆点】ARC061Cすぬけ君の地下鉄旅行/Snuke's Subway Trip
    【数学-思维-枚举方式】ARC060B 桁和/Digit Sum
    ARC107C Shuffle Permutation【有脑就行qwq/完全不知道怎么分类嘛】
    【kmp-循环节】ARC060D 最良表現/Best Representation
    【简单dp】ARC059C キャンディーとN人の子供 / Children and Candies
    【状压】ARC058E 和風いろはちゃん / Iroha and Haiku
    快速乘
    Miller Rabin素数测试和Pollard Rho算法
    JAVA补充-接口
  • 原文地址:https://www.cnblogs.com/gxlaqj/p/11483000.html
Copyright © 2020-2023  润新知