zoukankan      html  css  js  c++  java
  • spring shiro 集成

    1、向spring项目中添加shiro相关的依赖

            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.1.3</version>
            </dependency>
            <dependency>
                <groupId>commons-collections</groupId>
                <artifactId>commons-collections</artifactId>
                <version>3.2.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>1.2.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-web</artifactId>
                <version>1.2.2</version>
            </dependency>
            <dependency>
                <groupId>net.sf.ehcache</groupId>
                <artifactId>ehcache-core</artifactId>
                <version>2.6.8</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-ehcache</artifactId>
                <version>1.2.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-quartz</artifactId>
                <version>1.2.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.2.2</version>
            </dependency>
    View Code

    2、在web.xml配置ShiroFilter

    <!-- shiro过虑器,DelegatingFilterProx会从spring容器中找shiroFilter -->
    <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>
    View Code

     3、建立一个 spring 的配置文件 spring-shiro.xml

      a、使用 import 标签把此文件引入为spring的配置文件

    <import resource="classpath:spring-shiro.xml"></import>

      b、配置spring-shiro.xml文件

        <!-- shiro 拦截器配置 -->
        <!-- ShiroFilter 名字必须要和web.xml中配置的名字一致 -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager"/>
            <property name="loginUrl" value="/login"/>
            <property name="unauthorizedUrl" value="/nopermission.jsp"/>
            <!-- filterChainDefinitions 相当于.ini文件中的[urls] -->
            <property name="filterChainDefinitions">
                <value>
                    /logout=logout
                    /**=authc
                </value>
            </property>
        </bean>
        <!--shiro权限异常处理 -->
        <!-- 上面对“/nopermission.jsp”的配置不会生效,因为 spring 默认会抛出异常到页面;需要添加下面这个配置才可以生效-->
        <!-- 定义需要特殊处理的异常,用类名或完全路径名作为key,异常页名作为值 -->
        <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
            <property name="exceptionMappings">
                <props>
                    <prop key="org.apache.shiro.authz.UnauthorizedException">redirect:/nopermission.jsp</prop>
                </props>
            </property>
        </bean>
    
        <!-- 配置安全管理器SecurityManager -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="userRealm"/>
            <!-- 给shiro添加缓存配置 -->
            <property name="cacheManager" ref="cacheManager"></property>
        </bean>
        <!-- 配置自定义的Realm -->
        <bean id="userRealm" class="cn.wolfcode.shiro.realm.UserRealm">
            <!-- 加密器 -->
            <property name="credentialsMatcher" ref="credentialsMatcher" />
        </bean>
        <!-- 在自定义的realm那个类里还要指定盐 -->
        <bean id="credentialsMatcher"
              class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
            <!-- 加密算法 -->
            <property name="hashAlgorithmName" value="md5" />
            <!-- 散列次数 -->
            <property name="hashIterations" value="3" />
        </bean>
    
        <!-- 开启aop,对类代理;并开启shiro注解支持 -->
        <aop:config proxy-target-class="true"></aop:config>
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager" />
        </bean>
    
        <!-- 缓存管理器 -->
        <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
            <property name="cacheManager" ref="ehCacheManager"/>
        </bean>
        <bean id="ehCacheManager" class ="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
            <property name="configLocation" value="classpath:shiro-ehcache.xml" />
            <property name="shared" value="true"></property>
        </bean>

    4、实现自己的realm

    public class UserRealm extends AuthorizingRealm {
        @Override
        public String getName() {
            return "UserRealm";
        }
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String principal = (String) token.getPrincipal();
            if(!"admin".equals(principal)){
                return null;
            }
            Employee currentUser = new Employee();
            currentUser.setName(principal);
            currentUser.setPassword("1");
            currentUser.setAdmin(true);
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(currentUser, currentUser.getPassword(),getName());
            return authenticationInfo;
        }
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            Employee currentUser = (Employee) principals.getPrimaryPrincipal();
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            List<String> roles = new ArrayList<String>();
            roles.addAll(Arrays.asList("HR MGR","ORDER MGR"));
            authorizationInfo.addRoles(roles);
            List<String> perms = new ArrayList<String>();
            perms.addAll(Arrays.asList("employee:view","employee:delete"));
            authorizationInfo.addStringPermissions(perms);
            return authorizationInfo;
        }
    }
    View Code

    5、 实现登陆方法

    Suject 会自动创建,不需要我们配置;相应的登陆方法也会自动调用,不需要我们写。

        //此方法不处理登陆成功(认证成功),shiro认证成功会自动跳转到上一个请求路径
        @RequestMapping("/login")
        public String login(Model model, HttpServletRequest req) throws  Exception{
            //如果登陆失败从request中获取认证异常信息,shiroLoginFailure就是shiro异常类的全限定名
            String exceptionClassName = (String) req.getAttribute("shiroLoginFailure");
            //根据shiro返回的异常类路径判断,抛出指定异常信息
            if(exceptionClassName!=null){
                if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
                    //最终会抛给异常处理器
    
                    model.addAttribute("errorMsg", "账号不存在");
                } else if (IncorrectCredentialsException.class.getName().equals(
                        exceptionClassName)) {
                    model.addAttribute("errorMsg", "用户名/密码错误");
                } else {
                    //最终在异常处理器生成未知错误.
                    model.addAttribute("errorMsg", "其他异常信息");
                }
            }
            //登陆失败还到login页面
            return "forward:/login.jsp";
        }
    View Code

    6、缓存管理(登陆时把当前用户的权限缓存起来,之后不需要再次查询)

      a、添加依赖

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.2.2</version>
    </dependency>
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-core</artifactId>
        <version>2.6.8</version>
    </dependency>
    View Code

      b、securityManager引用缓存管理器(如上)

      c、配置缓存管理器,并指定缓存框架配置文件路径(如上)

        ehcache版本在2.5.0以下,需要配置如下:
        <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
          <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"></property>
        </bean>
        ehcache版本在2.5.0以上,需要配置如下:
        <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
          <property name="cacheManager" ref="ehCacheManager"/>
        </bean>
        <bean id="ehCacheManager" class ="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
          <property name="configLocation" value="classpath:shiro-ehcache.xml" />
          <property name="shared" value="true"></property>
        </bean>

      d、配置 shiro-ehcache.xml 文件

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache>
        <defaultCache
                maxElementsInMemory="1000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                memoryStoreEvictionPolicy="LRU">
        </defaultCache>
    </ehcache>

    7、清除缓存

      如果用户正常退出,缓存自动清空;如果用户非正常退出,缓存自动清空。

      如果修改了用户的权限,而用户不退出系统,修改的权限无法立即生效;用户退出并再次登陆系统时,shiro会自动调用realm从数据库重新获取权限数据,才会使修改的权限得以生效。

      如果在修改权限后想要立即生效,需要清除缓存,可以调用realm的clearCache方法。

    // 在realm中定义该方法,在角色或权限service中,delete或者update方法里来调用
    // 清除缓存
    public void clearCached() {
         PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
         super.clearCache(principals);
    }
  • 相关阅读:
    MongoDB优化之一:常见优化方法
    Spark Streaming之一:整体介绍
    Java中实现MongoDB自增主键ID
    RDD之一:总体介绍
    对一致性Hash算法,Java代码实现的深入研究
    MongoDB 创建基础索引、组合索引、唯一索引以及优化
    mongo-查询
    MongoTemplate聚合操作
    RESTLET开发实例(一)基于JAX-RS的REST服务
    Hashtable的实现原理
  • 原文地址:https://www.cnblogs.com/Mike_Chang/p/9903636.html
Copyright © 2011-2022 走看看