zoukankan      html  css  js  c++  java
  • 第八讲 shiro 整合 ssm

    1、整合ssm并且实现用户登录和菜单权限

    2、将shiro整合到ssm中

      (1)添加shiro相关jar包

      (2)在web.xml中添加shiro配置

     1     <!-- 新增shiro配置 -->
     2     <!-- 配置shiroFilter,通过代理来配置,对象由spring容器来创建的,但是交由servlet容器来管理 -->
     3     <filter>
     4         <filter-name>shiroFilter</filter-name>
     5         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
     6         <init-param>
     7             <!-- 表示bean的生命周期由servlet管理 -->
     8             <param-name>targetFilterLifecycle</param-name>
     9             <param-value>true</param-value>
    10         </init-param>
    11 
    12         <init-param>
    13             <!-- 表示在spring容器中bean的id,如果不配置该属性,那么默认和filter的name一致 -->
    14             <param-name>targetBeanName</param-name>
    15             <param-value>shiroFilter</param-value>
    16         </init-param>
    17 
    18     </filter>
    19 
    20     <filter-mapping>
    21         <filter-name>shiroFilter</filter-name>
    22         <url-pattern>/*</url-pattern>
    23     </filter-mapping>
    24 
    25     <!-- shiro结束 -->

      (3)添加applicationContext-shiro.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
    
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <!-- 配置securityManager -->
            <property name="securityManager" ref="securityManager"/>
            <!-- 当访问需要认证的资源时,如果没有认证,那么将自动跳转到该url;
            如果不配置该属性,默认情况下货到根路径下的login.jsp -->
            <!-- controller层查看地址配置 -->
            <property name="loginUrl" value="/login"></property>
            <!-- 配置认证成功后,跳转到那个url上,通常不设置,如果不设置,那么默认认证成功后跳转到上一个url -->
            <property name="successUrl" value="/index"></property>
            <!-- 配置用户没有权限访问资源时,跳转的页面     /refuse自定义 -->
            <property name="unauthorizedUrl" value="/refuse"></property>
            <!-- 配置shiro的过滤器链 -->
            <property name="filterChainDefinitions">
                <value>
                    <!-- anon表示匿名 -->
                    /toLogin=anon
                    /login=authc
                    /logout=logout

               /js/**=anon
               /css/**=anon
               /images/**=anon

                    /**=authc
                </value>
            </property>
        </bean>
        
        <!-- 配置securityManager -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="userRealm"/>
        </bean>
        
        <bean id="userRealm" class="com.sun123.template.realm.UserRealm"/>
        
        
    </beans>

      (4)修改LoginController中的登录方法

    package com.sun123.template.conrtroller;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    @Controller
    public class LoginController {
    
        @RequestMapping(value = {"/","index"})
        public ModelAndView index() {
            return new ModelAndView("index");
        }
        
        //去登录页面
        @RequestMapping("/toLogin")
        public ModelAndView toLogin() {
            return new ModelAndView("login");
        }
        
        //登录
        @RequestMapping("/login")
        public ModelAndView login(HttpServletRequest request) {
            System.out.println("========login=======");
            ModelAndView mv = new ModelAndView("login");
            String className = (String)request.getAttribute("shiroLoginFailure");
            if (UnknownAccountException.class.getName().equals(className)) {
                //抛出自定义异常
                mv.addObject("msg","用户名或密码错误");
            }else if (IncorrectCredentialsException.class.getName().equals(className)) {
                //抛出自定义异常
                mv.addObject("msg","用户名或密码错误");
            } else {
                //抛出自定义异常
                mv.addObject("msg","系统异常");
            }
            
            return mv;
            
        }
        
        //访问被拒绝
        @RequestMapping("/refuse")
        public ModelAndView refuse() {
            return new ModelAndView("refuse");
        }
    }

      (5)添加自定义Realm:UserRealm.java

    package com.sun123.template.realm;
    
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    
    public class UserRealm extends AuthorizingRealm {
    
        @Override
        public String getName() {
            // TODO Auto-generated method stub
            return "userRealm";
        }
        
        //获取认证信息
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("---------认证----------------");
            String username = token.getPrincipal().toString();
            String pwd = "1111";
            
            return new SimpleAuthenticationInfo(username,pwd,getName());
        }
        
        //获取授权信息
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
            
            
            return null;
        }
    
        
    
    }

    3、修改UserRealm实现自定义认证

     1 package com.sun123.template.realm;
     2 
     3 import org.apache.shiro.authc.AuthenticationException;
     4 import org.apache.shiro.authc.AuthenticationInfo;
     5 import org.apache.shiro.authc.AuthenticationToken;
     6 import org.apache.shiro.authc.SimpleAuthenticationInfo;
     7 import org.apache.shiro.authz.AuthorizationInfo;
     8 import org.apache.shiro.realm.AuthorizingRealm;
     9 import org.apache.shiro.subject.PrincipalCollection;
    10 import org.springframework.beans.factory.annotation.Autowired;
    11 
    12 import com.sun123.template.entity.User;
    13 import com.sun123.template.service.UserService;
    14 
    15 public class UserRealm extends AuthorizingRealm {
    16 
    17     @Autowired
    18     private UserService userService;
    19     
    20     @Override
    21     public String getName() {
    22         // TODO Auto-generated method stub
    23         return "userRealm";
    24     }
    25     
    26     //获取认证信息
    27     @Override
    28     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    29         System.out.println("---------认证----------------");
    30         String username = token.getPrincipal().toString();
    31         User user = userService.findByUserName(username); 
    32         return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
    33     }
    34     
    35     //获取授权信息
    36     @Override
    37     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
    38 
    39         return null;
    40     }
    41 
    42     
    43 
    44 }

    4、凭证匹配器配置

     1     <!-- 配置自定义realm -->
     2     <bean id="userRealm" class="com.sun123.template.realm.UserRealm">
     3         <property name="credentialsMatcher" ref="credentialsMatcher" />
     4     </bean>
     5     <!-- 配置凭证匹配器 -->
     6     <bean id="credentialsMatcher"
     7         class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
     8         <property name="hashAlgorithmName" value="md5" />
     9         <!-- 迭代次数 -->
    10         <property name="hashIterations" value="2" />
    11     </bean>

      UserRealm.java要相应改变

     1 package com.sun123.template.realm;
     2 
     3 import org.apache.shiro.authc.AuthenticationException;
     4 import org.apache.shiro.authc.AuthenticationInfo;
     5 import org.apache.shiro.authc.AuthenticationToken;
     6 import org.apache.shiro.authc.SimpleAuthenticationInfo;
     7 import org.apache.shiro.authz.AuthorizationInfo;
     8 import org.apache.shiro.realm.AuthorizingRealm;
     9 import org.apache.shiro.subject.PrincipalCollection;
    10 import org.apache.shiro.util.ByteSource;
    11 import org.springframework.beans.factory.annotation.Autowired;
    12 
    13 import com.sun123.template.entity.User;
    14 import com.sun123.template.service.UserService;
    15 
    16 public class UserRealm extends AuthorizingRealm {
    17 
    18     @Autowired
    19     private UserService userService;
    20     
    21     @Override
    22     public String getName() {
    23         // TODO Auto-generated method stub
    24         return "userRealm";
    25     }
    26     
    27     //获取认证信息
    28     @Override
    29     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    30         System.out.println("---------认证----------------");
    31         String username = token.getPrincipal().toString();
    32         User user = userService.findByUserName(username); 
    33         return new SimpleAuthenticationInfo(user,user.getPassword(),ByteSource.Util.bytes(user.getPasswordSalt()),getName());
    34     }
    35     
    36     //获取授权信息
    37     @Override
    38     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
    39 
    40         return null;
    41     }
    42 
    43     
    44 
    45 }

    5、logout配置,默认退出后跳转到根路径下,如果需要改变则需重新配置logout过滤器,过滤器的id不能改变,只能为logout

     1     <bean id="shiroFilter"
     2         class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
     3         <!-- 配置securityManager -->
     4         <property name="securityManager" ref="securityManager" />
     5         <!-- 当访问需要认证的资源时,如果没有认证,那么将自动跳转到该url; 如果不配置该属性,默认情况下货到根路径下的login.jsp -->
     6         <!-- controller层查看地址配置 -->
     7         <property name="loginUrl" value="/login"></property>
     8         <!-- 配置认证成功后,跳转到那个url上,通常不设置,如果不设置,那么默认认证成功后跳转到上一个url -->
     9         <property name="successUrl" value="/index"></property>
    10         <!-- 配置用户没有权限访问资源时,跳转的页面 /refuse自定义 -->
    11         <property name="unauthorizedUrl" value="/refuse"></property>
    12         <!-- 配置shiro的过滤器链
    13             logout默认退出后跳转到根路径下,可以重新指定
    14          -->
    15         <property name="filterChainDefinitions">
    16             <value>
    17                 <!-- anon表示匿名 -->
    18                 /toLogin=anon
    19                 /login=authc
    20                 /logout=logout
    21                 /js/**=anon
    22                 /css/**=anon
    23                 /images/**=anon
    24                 /**=authc
    25             </value>
    26         </property>
    27     </bean>
    28 
    29     <!-- 配置authc过滤器(用户名和密码不使用默认配置username,password) -->
    30     <bean id="authc" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
    31         <property name="usernameParam" value="name"/>
    32         <property name="passwordParam" value="pwd"/>
    33     </bean>
    34     
    35     <!-- 配置logout过滤器 -->
    36     <bean id="logout" class="org.apache.shiro.web.filter.authc.LogoutFilter">
    37         <property name="redirectUrl" value="/toLogin"/>
    38     </bean>

    6、改变登录时的表单域名称,需要重新配置authc过滤器

     1     <bean id="shiroFilter"
     2         class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
     3         <!-- 配置securityManager -->
     4         <property name="securityManager" ref="securityManager" />
     5         <!-- 当访问需要认证的资源时,如果没有认证,那么将自动跳转到该url; 如果不配置该属性,默认情况下货到根路径下的login.jsp -->
     6         <!-- controller层查看地址配置 -->
     7         <property name="loginUrl" value="/login"></property>
     8         <!-- 配置认证成功后,跳转到那个url上,通常不设置,如果不设置,那么默认认证成功后跳转到上一个url -->
     9         <property name="successUrl" value="/index"></property>
    10         <!-- 配置用户没有权限访问资源时,跳转的页面 /refuse自定义 -->
    11         <property name="unauthorizedUrl" value="/refuse"></property>
    12         <!-- 配置shiro的过滤器链
    13             logout默认退出后跳转到根路径下,可以重新指定
    14          -->
    15         <property name="filterChainDefinitions">
    16             <value>
    17                 <!-- anon表示匿名 -->
    18                 /toLogin=anon
    19                 /login=authc
    20                 /logout=logout
    21                 /js/**=anon
    22                 /css/**=anon
    23                 /images/**=anon
    24                 /**=authc
    25             </value>
    26         </property>
    27     </bean>
    28 
    29     <!-- 配置authc过滤器(用户名和密码不使用默认配置username,password) -->
    30     <bean id="authc" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
    31         <property name="usernameParam" value="name"/>
    32         <property name="passwordParam" value="pwd"/>
    33     </bean>

      登录页面的改变:

    1 <form action="login" method="post">
    2 <!--     username:<input type="text" name="username"><br/>
    3     password:<input type="password" name="password"><br/> -->
    4     username:<input type="text" name="name"><br/>
    5     password:<input type="password" name="pwd"><br/>
    6     <input type="submit" value="login"> 
    7 </form>

     7、授权

      (1)修改自定义Realm进行权限检查

      

      (2)在spring-mvc的配置文件中,添加AOP代理,并且添加异常处理

      

    1     <!-- 开启AOP代理 -->
    2     <aop:config proxy-target-class="true"></aop:config>
    3     <!-- 开启Shiro注解支持 -->
    4     <bean
    5         class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    6         <property name="securityManager" ref="securityManager" />
    7     </bean>

      在controller的处理方法中,添加权限检测的注解

      

      在jsp页面中,添加按钮权限检测,首先需要导入shiro的标签库

      

      在需要检查权限的地方,使用shiro标签

      

     8、缓存

      每次检查权限都会到数据库中获取权限,这样效率很低。可以通过设置缓存来解决该问题。Shiro可以和ehcache或者redis集成。这里使用ehcache来缓存数据。

      (1)将ehcache,jar导入系统。

      (2)shiro默认集成了一个ehcache的配置文件。也可以自己添加一个进行配置,放入resources下。

      ehcache.xml:

     1 <ehcache>
     2     <diskStore path="java.io.tmpdir/shiro-ehcache"/>
     3     <defaultCache
     4             maxElementsInMemory="10000"
     5             eternal="false"
     6             timeToIdleSeconds="120"
     7             timeToLiveSeconds="120"
     8             overflowToDisk="false"
     9             diskPersistent="false"
    10             diskExpiryThreadIntervalSeconds="120"
    11             />
    12 </ehcache>

      (3)在applicationContext-shiro.xml中,添加cacheManager的配置

     1     <!-- 配置securityManager -->
     2     <bean id="securityManager"
     3         class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
     4         <property name="realm" ref="userRealm" />
     5         <property name="cacheManager" ref="cacheManager"></property>
     6     </bean>
     7     <!-- 配置缓存管理器 -->
     8     <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
     9         <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
    10     </bean>

      (4)如果在运行过程中,主体的权限发生了改变,那么应该从spring容器中调用realm中的清理缓存方法,进行清理。

      UserRealm.java中添加清理缓存方法

    1     //清理缓存方法
    2     protected void clearCache() {
    3         Subject subject = SecurityUtils.getSubject();
    4         super.clearCache(subject.getPrincipals());
    5     }

    9、会话管理

     1     <!-- 配置securityManager -->
     2     <bean id="securityManager"
     3         class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
     4         <property name="realm" ref="userRealm" />
     5         <property name="cacheManager" ref="cacheManager"/>
     6         <property name="sessionManager" ref="sessionManager"/>
     7     </bean>
     8     <!-- 配置缓存管理器 -->
     9     <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    10         <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
    11     </bean>
    12     
    13     <!-- 配置会话管理器 -->
    14     <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    15         <!-- 失效时间单位是毫秒 -->
    16         <property name="globalSessionTimeout" value="300000"/>
    17         <!-- 删除无效session -->
    18         <property name="deleteInvalidSessions" value="true"/>
    19     </bean>

    10、记住我

      (1)将用户类实现序列化接口,该类的引用类也必须实现序列化接口

      (2)设置登录时表单中“记住我”的域名

    1     <!-- 配置authc过滤器(用户名和密码不使用默认配置username,password) -->
    2     <bean id="authc" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
    3         <property name="usernameParam" value="name"/>
    4         <property name="passwordParam" value="pwd"/>
    5         <property name="rememberMeParam" value="rememberMe"/>
    6     </bean>

      (3)设置“记住我”管理器

     1     <!-- 配置securityManager -->
     2     <bean id="securityManager"
     3         class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
     4         <property name="realm" ref="userRealm" />
     5         <property name="cacheManager" ref="cacheManager"/>
     6         <property name="sessionManager" ref="sessionManager"/>
     7         <property name="rememberMeManager" ref="rememberMeManager"/>
     8     </bean>
     9     <!-- 配置缓存管理器 -->
    10     <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    11         <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
    12     </bean>
    13     
    14     <!-- 配置会话管理器 -->
    15     <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    16         <!-- 失效时间单位是毫秒 -->
    17         <property name="globalSessionTimeout" value="300000"/>
    18         <!-- 删除无效session -->
    19         <property name="deleteInvalidSessions" value="true"/>
    20     </bean>
    21     <!-- 记住我配置 -->
    22     <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
    23         <property name="cookie" ref="rememberMeCookie"></property>
    24     </bean>
    25     <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    26         <!-- 设置cookie存活时间    保存7天 -->
    27         <property name="maxAge" value="604800"/>
    28         <!-- 设置cookie的名称 -->
    29         <property name="name" value="rememberMe"/>
    30     </bean>
    31     <!-- 记住我配置结束 -->

      (4)在过滤器链中配置哪些资源通过记住我就可以再次访问

     1         <!-- 配置shiro的过滤器链
     2             logout默认退出后跳转到根路径下,可以重新指定
     3          -->
     4         <property name="filterChainDefinitions">
     5             <value>
     6                 <!-- anon表示匿名 -->
     7                 /toLogin=anon
     8                 /login=authc
     9                 /logout=logout
    10                 /js/**=anon
    11                 /css/**=anon
    12                 /images/**=anon
    13                 /easyui/**=anon
    14  /index=user
    15                 /**=authc
    16             </value>
    17         </property>

      (5)jsp页面设置

    1 <form action="login" method="post">
    2 <!--     username:<input type="text" name="username"><br/>
    3     password:<input type="password" name="password"><br/> -->
    4     username:<input type="text" name="name"><br/>
    5     password:<input type="password" name="pwd"><br/>
    6     <input type="checkbox" name="rememberMe">记住我<br/>
    7     <input type="submit" value="login"> 
    8 </form>
  • 相关阅读:
    Java并发初识
    go交叉编译
    MRC与ARC混合开发配置
    Hibernate配置文件
    LEFT JOIN重复数据
    Ext.ViewPort布局
    Hibernate学习映射文件
    AjaxMethod方法
    DataBinder
    subsonic 获取记录数量
  • 原文地址:https://www.cnblogs.com/116970u/p/10956674.html
Copyright © 2011-2022 走看看