shiro環境搭建及基本操做

1、pom.xmlcss

  1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3   <modelVersion>4.0.0</modelVersion>
  4   <groupId>com.sh</groupId>
  5   <artifactId>shirotest</artifactId>
  6   <packaging>war</packaging>
  7   <version>0.0.1-SNAPSHOT</version>
  8   <name>shirotest Maven Webapp</name>
  9   <url>http://maven.apache.org</url>
 10 
 11   <dependencies>
 12   
 13   
 14 <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-all -->
 15 <dependency>
 16     <groupId>org.apache.shiro</groupId>
 17     <artifactId>shiro-all</artifactId>
 18     <version>1.2.2</version>
 19 </dependency>
 20 <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
 21 <dependency>
 22     <groupId>org.apache.commons</groupId>
 23     <artifactId>commons-lang3</artifactId>
 24     <version>3.4</version>
 25 </dependency>
 26   
 27   
 28 <dependency>
 29     <groupId>javax.servlet</groupId>
 30     <artifactId>servlet-api</artifactId>
 31     <version>2.5</version>
 32     <scope>provided</scope>
 33 </dependency>
 34     <dependency>
 35       <groupId>junit</groupId>
 36       <artifactId>junit</artifactId>
 37       <version>3.8.1</version>
 38       <scope>test</scope>
 39     </dependency>
 40     <!-- https://mvnrepository.com/artifact/jstl/jstl -->
 41 <dependency>
 42     <groupId>jstl</groupId>
 43     <artifactId>jstl</artifactId>
 44     <version>1.2</version>
 45 </dependency>
 46     <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
 47     <dependency>
 48         <groupId>org.springframework</groupId>
 49         <artifactId>spring-aop</artifactId>
 50         <version>3.2.0.RELEASE</version>
 51     </dependency>
 52     <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
 53     <dependency>
 54         <groupId>org.springframework</groupId>
 55         <artifactId>spring-aspects</artifactId>
 56         <version>3.2.0.RELEASE</version>
 57     </dependency>
 58     <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
 59     <dependency>
 60         <groupId>org.springframework</groupId>
 61         <artifactId>spring-beans</artifactId>
 62         <version>3.2.0.RELEASE</version>
 63     </dependency>
 64     <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
 65     <dependency>
 66         <groupId>org.springframework</groupId>
 67         <artifactId>spring-context</artifactId>
 68         <version>3.2.0.RELEASE</version>
 69     </dependency>
 70     <!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
 71     <dependency>
 72         <groupId>org.springframework</groupId>
 73         <artifactId>spring-context-support</artifactId>
 74         <version>3.2.0.RELEASE</version>
 75     </dependency>
 76     <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
 77     <dependency>
 78         <groupId>org.springframework</groupId>
 79         <artifactId>spring-core</artifactId>
 80         <version>3.2.0.RELEASE</version>
 81     </dependency>
 82     <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
 83     <dependency>
 84         <groupId>org.springframework</groupId>
 85         <artifactId>spring-expression</artifactId>
 86         <version>3.2.0.RELEASE</version>
 87     </dependency>
 88     <!-- https://mvnrepository.com/artifact/org.springframework/spring-instrument -->
 89     <dependency>
 90         <groupId>org.springframework</groupId>
 91         <artifactId>spring-instrument</artifactId>
 92         <version>3.2.0.RELEASE</version>
 93     </dependency>
 94     <!-- https://mvnrepository.com/artifact/org.springframework/spring-instrument-tomcat -->
 95     <dependency>
 96         <groupId>org.springframework</groupId>
 97         <artifactId>spring-instrument-tomcat</artifactId>
 98         <version>3.2.0.RELEASE</version>
 99     </dependency>
100      <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
101     <dependency>
102         <groupId>org.springframework</groupId>
103         <artifactId>spring-jdbc</artifactId>
104         <version>3.2.0.RELEASE</version>
105     </dependency>
106      <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
107     <dependency>
108         <groupId>org.springframework</groupId>
109         <artifactId>spring-orm</artifactId>
110         <version>3.2.0.RELEASE</version>
111     </dependency>
112      <!-- https://mvnrepository.com/artifact/org.springframework/spring-oxm -->
113     <dependency>
114         <groupId>org.springframework</groupId>
115         <artifactId>spring-oxm</artifactId>
116         <version>3.2.0.RELEASE</version>
117     </dependency>
118      <!-- https://mvnrepository.com/artifact/org.springframework/spring-struts -->
119     <dependency>
120         <groupId>org.springframework</groupId>
121         <artifactId>spring-struts</artifactId>
122         <version>3.2.0.RELEASE</version>
123     </dependency>
124      <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
125     <dependency>
126         <groupId>org.springframework</groupId>
127         <artifactId>spring-test</artifactId>
128         <version>3.2.0.RELEASE</version>
129     </dependency>
130     <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
131     <dependency>
132         <groupId>org.springframework</groupId>
133         <artifactId>spring-tx</artifactId>
134         <version>3.2.0.RELEASE</version>
135     </dependency>
136     <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
137     <dependency>
138         <groupId>org.springframework</groupId>
139         <artifactId>spring-web</artifactId>
140         <version>3.2.0.RELEASE</version>
141     </dependency>
142     <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
143     <dependency>
144         <groupId>org.springframework</groupId>
145         <artifactId>spring-webmvc</artifactId>
146         <version>3.2.0.RELEASE</version>
147     </dependency>
148     <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc-portlet -->
149     <dependency>
150         <groupId>org.springframework</groupId>
151         <artifactId>spring-webmvc-portlet</artifactId>
152         <version>3.2.0.RELEASE</version>
153     </dependency>
154   </dependencies>
155   <build>
156     <finalName>shirotest</finalName>
157   </build>
158 </project>
View Code

 2、SpringMvc.xmlhtml

 1 <beans xmlns="http://www.springframework.org/schema/beans"
 2  xmlns:context="http://www.springframework.org/schema/context"
 3  xmlns:p="http://www.springframework.org/schema/p"
 4  xmlns:mvc="http://www.springframework.org/schema/mvc"
 5  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 6  xsi:schemaLocation="http://www.springframework.org/schema/beans
 7       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 8       http://www.springframework.org/schema/context
 9       http://www.springframework.org/schema/context/spring-context.xsd
10       http://www.springframework.org/schema/mvc
11       http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
12      <!-- 啓動註解驅動的Spring MVC功能,註冊請求url和註解POJO類方法的映射-->
13      <mvc:annotation-driven />
14      <!-- 啓動包掃描功能,以便註冊帶有@Controller、@Service、@repository、@Component等註解的類成爲spring的bean -->
15      <context:component-scan base-package="com.**.controller" />
16       <mvc:default-servlet-handler/>  
17      <!-- 對模型視圖名稱的解析,在請求時模型視圖名稱添加先後綴 -->
18      <!-- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/" p:suffix=".jsp" /> -->
19      <bean
20         class="org.springframework.web.servlet.view.InternalResourceViewResolver">
21         <property name="prefix">
22             <value>/</value>
23         </property>
24         <property name="suffix">
25             <value>.jsp</value>
26         </property>
27     </bean>
28 
29     <!-- shiro註解啓用,不可配置在shiro.xml中 -->
30     <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
31     <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
32         <property name="securityManager" ref="securityManager"/>
33     </bean>
34     
35     <!-- shiro註解攔截未受權時跳轉頁面 -->
36     <bean  class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
37     <property name="exceptionMappings">  
38         <props>  
39             <prop key="org.apache.shiro.authz.AuthorizationException">  
40                 /meishouquan  <!-- //捕獲該異常時跳轉的路徑 -->
41             </prop>  
42         
43         </props>  
44     </property>  
45 </bean> 
46 </beans>
View Code

3、web.xmljava

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
 3      <session-config>
 4         <session-timeout>120</session-timeout>
 5     </session-config>
 6   <context-param>
 7     <param-name>contextConfigLocation</param-name>
 8     <param-value>/WEB-INF/spring-*.xml</param-value>
 9   </context-param>
10   <listener>
11     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
12   </listener>
13   <servlet-mapping>
14     <servlet-name>default</servlet-name>
15     <url-pattern>*.jpg</url-pattern>
16   </servlet-mapping>
17   <servlet-mapping>
18     <servlet-name>default</servlet-name>
19     <url-pattern>*.js</url-pattern>
20   </servlet-mapping>
21   <servlet-mapping>
22     <servlet-name>default</servlet-name>
23     <url-pattern>*.css</url-pattern>
24   </servlet-mapping>
25   <servlet-mapping>
26     <servlet-name>default</servlet-name>
27     <url-pattern>*.docx</url-pattern>
28   </servlet-mapping>
29   <servlet>
30     <servlet-name>spring</servlet-name>
31     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
32     <load-on-startup>1</load-on-startup>
33   </servlet>
34   <servlet-mapping>
35     <servlet-name>spring</servlet-name>
36     <url-pattern>/</url-pattern>
37   </servlet-mapping>
38   
39    <!--
40     配置Shiro過濾器
41     這裏filter-name必須對應spring-shiro.xml中定義的<bean id="shiroFilter"/>
42     使用[/*]匹配全部請求,保證全部的可控請求都通過Shiro的過濾
43     一般會將此filter-mapping放置到最前面(即其餘filter-mapping前面),以保證它是過濾器鏈中第一個起做用的
44     -->
45     <filter>
46         <filter-name>shiroFilter</filter-name>
47         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
48         <init-param>
49             <!-- 缺省爲false,表示由SpringApplicationContext管理生命週期,置爲true則表示由ServletContainer管理 -->
50             <param-name>targetFilterLifecycle</param-name>
51             <param-value>true</param-value>
52         </init-param>
53     </filter>
54     <filter-mapping>
55         <filter-name>shiroFilter</filter-name>
56         <url-pattern>/*</url-pattern>
57     </filter-mapping>
58 </web-app>
View Code

4、spring-shiro.xmlweb

 1 <beans xmlns="http://www.springframework.org/schema/beans"
 2  xmlns:context="http://www.springframework.org/schema/context"
 3  xmlns:p="http://www.springframework.org/schema/p"
 4  xmlns:mvc="http://www.springframework.org/schema/mvc"
 5  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 6  xsi:schemaLocation="http://www.springframework.org/schema/beans
 7       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 8       http://www.springframework.org/schema/context
 9       http://www.springframework.org/schema/context/spring-context.xsd
10       http://www.springframework.org/schema/mvc
11       http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
12      
13      
14      <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
15         <!-- 指定Shiro驗證用戶登陸的類爲自定義的Realm(如有多個Realm,可以使用[realms]屬性代替) -->
16         <property name="realm">
17             <bean class="com.sh.realm.MyRealm"/>
18         </property>
19         <!--
20         Shiro默認會使用Servlet容器的Session,此時修改超時時間的話,能夠修改web.xml或者這裏自定義的MyRealm
21         而若想使用Shiro原生Session則能夠設置sessionMode屬性爲native,此時修改超時時間則只能修改MyRealm
22         -->
23         <!-- <property name="sessionMode" value="native"/> -->
24     </bean>
25 
26     <!-- Shiro主過濾器自己功能十分強大,其強大之處就在於它支持任何基於URL路徑表達式的、自定義的過濾器的執行 -->
27     <!-- Web應用中,Shiro可控制的Web請求必須通過Shiro主過濾器的攔截,而且Shiro對基於Spring的Web應用提供了完美的支持 -->
28     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
29         <!-- Shiro的核心安全接口,這個屬性是必須的 -->
30         <property name="securityManager" ref="securityManager"/>
31         <!-- 要求登陸時的連接(可根據項目的URL進行替換),非必須的屬性,默認會找Web工程根目錄下的[/login.jsp] -->
32         <property name="loginUrl" value="/login.jsp"/>
33         <!-- 登陸成功後要跳轉的鏈接(本例中此屬性用不到,由於登陸成功後的處理邏輯已在LoginController中硬編碼爲main.jsp) -->
34         <!-- <property name="successUrl" value="/system/main"/> -->
35         <!-- 用戶訪問未受權的資源時,跳轉頁面-->
36         <property name="unauthorizedUrl" value="/meishouquan.jsp"/>
37         <!--攔截配置-->
38         <property name="filterChainDefinitions">
39             <value>
40                 /admin/list**     = authc,perms[admin:manage,admin:add] <!-- 必須登錄,而且具備[]裏的權限纔可訪問 -->
41                <!--  /admin/list**     = authc,roles[admin] --> <!-- 必須登錄,而且具備[]裏的角色纔可訪問 -->
42                 /user/info-anon** = anon<!-- 無需登陸 -->
43                 /user/info**      = authc<!-- 須要登錄 -->
44             </value>
45         </property>
46     </bean>
47 
48     <!-- 保證明現了Shiro內部lifecycle函數的bean執行 -->
49     <!-- http://shiro.apache.org/static/1.2.1/apidocs/org/apache/shiro/spring/LifecycleBeanPostProcessor.html -->
50     <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
51 
52     
53 <!--開啓Shiro的註解(好比@RequiresRoles、@RequiresPermissions)  配置如下兩個bean便可實現此功能-->
54     
55    <!-- 注意:**下面配置只能在spring.xml中配置生效,必須保證在加載第一個xml時加載此配置 -->
56     
57 <!--     <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
58     <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
59         <property name="securityManager" ref="securityManager"/>
60     </bean> -->
61    
62 
63 </beans>
View Code

5、添加頁面,點擊下載  spring

6、添加Controller代碼數據庫

  1 package com.sh.controller;
  2 
  3 import java.io.IOException;
  4 
  5 import javax.servlet.http.HttpServletRequest;
  6 import javax.servlet.http.HttpServletResponse;
  7 import javax.servlet.http.HttpSession;
  8 
  9 import org.apache.commons.lang3.StringUtils;
 10 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
 11 import org.apache.commons.lang3.builder.ToStringStyle;
 12 import org.apache.shiro.SecurityUtils;
 13 import org.apache.shiro.authc.AuthenticationException;
 14 import org.apache.shiro.authc.ExcessiveAttemptsException;
 15 import org.apache.shiro.authc.IncorrectCredentialsException;
 16 import org.apache.shiro.authc.LockedAccountException;
 17 import org.apache.shiro.authc.UnknownAccountException;
 18 import org.apache.shiro.authc.UsernamePasswordToken;
 19 import org.apache.shiro.authz.annotation.RequiresGuest;
 20 import org.apache.shiro.authz.annotation.RequiresPermissions;
 21 import org.apache.shiro.authz.annotation.RequiresRoles;
 22 import org.apache.shiro.authz.annotation.RequiresUser;
 23 import org.apache.shiro.subject.Subject;
 24 import org.apache.shiro.web.util.WebUtils;
 25 import org.springframework.stereotype.Controller;
 26 import org.springframework.web.bind.annotation.RequestMapping;
 27 import org.springframework.web.bind.annotation.RequestMethod;
 28 import org.springframework.web.servlet.view.InternalResourceViewResolver;
 29 
 30 /**
 31  * SpringMVC-3.2.4整合Shiro-1.2.2
 32  */
 33 @Controller
 34 @RequestMapping("mydemo")
 35 public class ShiroUserController {
 36       @RequestMapping(value="/test", method=RequestMethod.GET)
 37       public void test(String username, String password, HttpServletRequest request,HttpServletResponse response) throws IOException{
 38           //Subject currentUser = SecurityUtils.getSubject();
 39          // System.out.println(currentUser.);
 40           /*System.out.println(currentUser.isPermitted("admin:manage1"));//判斷是否有指定權限
 41           System.out.println(currentUser.hasRole("admin1"));//判斷是否有指定角色*/
 42           Object principal = SecurityUtils.getSubject().getPrincipal();//得到當前登陸用戶名
 43           response.getWriter().print(principal);
 44       }
 45     @RequestMapping("/logout")
 46     public String logout(HttpSession session){
 47         String currentUser = (String)session.getAttribute("currentUser");
 48         System.out.println("用戶[" + currentUser + "]準備登出");
 49         SecurityUtils.getSubject().logout();
 50         System.out.println("用戶[" + currentUser + "]已登出");
 51         return InternalResourceViewResolver.REDIRECT_URL_PREFIX + "/login.jsp";
 52     }
 53 
 54     @RequestMapping(value="/login", method=RequestMethod.POST)
 55     public String login(String username, String password, HttpServletRequest request){
 56         System.out.println("-------------------------------------------------------");
 57         String rand = (String)request.getSession().getAttribute("rand");
 58         String captcha = WebUtils.getCleanParam(request, "captcha");
 59         System.out.println("用戶["+username+"]登陸時輸入的驗證碼爲["+captcha+"],HttpSession中的驗證碼爲["+rand+"]");
 60         if(!StringUtils.equals(rand, captcha)){
 61             request.setAttribute("message_login", "驗證碼不正確");
 62             return InternalResourceViewResolver.FORWARD_URL_PREFIX + "/";
 63         }
 64         UsernamePasswordToken token = new UsernamePasswordToken(username, password);
 65        // token.setRememberMe(true);
 66         System.out.print("爲驗證登陸用戶而封裝的Token:");
 67         System.out.println(ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));
 68         //獲取當前的Subject
 69         Subject currentUser = SecurityUtils.getSubject();
 70         try {
 71             //在調用了login方法後,SecurityManager會收到AuthenticationToken,並將其發送給已配置的Realm執行必須的認證檢查
 72             //每一個Realm都能在必要時對提交的AuthenticationTokens做出反應
 73             //因此這一步在調用login(token)方法時,它會走到MyRealm.doGetAuthenticationInfo()方法中,具體驗證方式詳見此方法
 74             System.out.println("對用戶[" + username + "]進行登陸驗證...驗證開始");
 75             currentUser.login(token);
 76             System.out.println("對用戶[" + username + "]進行登陸驗證...驗證經過");
 77         }catch(UnknownAccountException uae){
 78             System.out.println("對用戶[" + username + "]進行登陸驗證...驗證未經過,未知帳戶");
 79             request.setAttribute("message_login", "未知帳戶");
 80         }catch(IncorrectCredentialsException ice){
 81             System.out.println("對用戶[" + username + "]進行登陸驗證...驗證未經過,錯誤的憑證");
 82             request.setAttribute("message_login", "密碼不正確");
 83         }catch(LockedAccountException lae){
 84             System.out.println("對用戶[" + username + "]進行登陸驗證...驗證未經過,帳戶已鎖定");
 85             request.setAttribute("message_login", "帳戶已鎖定");
 86         }catch(ExcessiveAttemptsException eae){
 87             System.out.println("對用戶[" + username + "]進行登陸驗證...驗證未經過,錯誤次數過多");
 88             request.setAttribute("message_login", "用戶名或密碼錯誤次數過多");
 89         }catch(AuthenticationException ae){
 90             //經過處理Shiro的運行時AuthenticationException就能夠控制用戶登陸失敗或密碼錯誤時的情景
 91             System.out.println("對用戶[" + username + "]進行登陸驗證...驗證未經過,堆棧軌跡以下");
 92             ae.printStackTrace();
 93             request.setAttribute("message_login", "用戶名或密碼不正確");
 94         }
 95         //驗證是否登陸成功
 96         if(currentUser.isAuthenticated()){
 97             System.out.println("用戶[" + username + "]登陸認證經過(這裏可進行一些認證經過後的系統參數初始化操做)");
 98             return "main";
 99         }else{
100             token.clear();
101             return InternalResourceViewResolver.FORWARD_URL_PREFIX + "/";
102         }
103     }
104     //屬於admin角色
105     //@RequiresRoles("admin")
106     //必須同時屬於user和admin角色
107     @RequiresRoles({"user","admin"})
108     //屬於user或者admin之一;修改logical爲OR 便可
109     //@RequiresRoles(value={"user","admin"},logical=Logical.OR)
110     @RequestMapping(value="/useRoles")
111     public void requiresRoles(HttpServletRequest request, HttpServletResponse response){
112         System.out.println("必須擁有指定角色");
113     }
114     //符合index:hello權限要求
115     @RequiresPermissions("admin:manage")
116     //必須同時複覈index:hello和index:world權限要求
117     //@RequiresPermissions({"index:hello","index:world"})
118     //符合index:hello或index:world權限要求便可
119     //@RequiresPermissions(value={"index:hello","index:world"},logical=Logical.OR)
120     @RequestMapping(value="/useper")
121     public void requiresPermissions(HttpServletRequest request, HttpServletResponse response){
122         System.out.println("必須擁有指定權限");
123     }
124   /*  驗證用戶是否被記憶,user有兩種含義:
125     一種是成功登陸的(subject.isAuthenticated() 結果爲true);
126     另一種是被記憶的(subject.isRemembered()結果爲true)。*/
127     @RequiresUser
128     @RequestMapping(value="/islogin")
129     public void requiresUser(HttpServletRequest request, HttpServletResponse response){
130         System.out.println("必須登陸或者記住登陸的");
131     }
132     //必須遊客訪問
133     @RequiresGuest
134     @RequestMapping(value="/isguest")
135     public void requiresGuest(HttpServletRequest request, HttpServletResponse response){
136         System.out.println("必須遊客");
137     }
138 }
View Code

7、添加Realm代碼express

  1 package com.sh.realm;
  2 
  3 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
  4 import org.apache.commons.lang3.builder.ToStringStyle;
  5 import org.apache.shiro.SecurityUtils;
  6 import org.apache.shiro.authc.AuthenticationException;
  7 import org.apache.shiro.authc.AuthenticationInfo;
  8 import org.apache.shiro.authc.AuthenticationToken;
  9 import org.apache.shiro.authc.SimpleAuthenticationInfo;
 10 import org.apache.shiro.authc.UsernamePasswordToken;
 11 import org.apache.shiro.authz.AuthorizationInfo;
 12 import org.apache.shiro.authz.SimpleAuthorizationInfo;
 13 import org.apache.shiro.realm.AuthorizingRealm;
 14 import org.apache.shiro.session.Session;
 15 import org.apache.shiro.subject.PrincipalCollection;
 16 import org.apache.shiro.subject.Subject;
 17 
 18 /**
 19  * 自定義的指定Shiro驗證用戶登陸的類
 20  * 這裏定義了兩個用戶:admin(擁有admin角色和admin:manage權限)、user(無任何角色和權限)
 21  */
 22 public class MyRealm extends AuthorizingRealm {
 23     /**
 24      * 爲當前登陸的Subject授予角色和權限
 25      * -----------------------------------------------------------------------------------------------
 26      * 經測試:本例中該方法的調用時機爲需受權資源被訪問時
 27      * 經測試:而且每次訪問需受權資源時都會執行該方法中的邏輯,這代表本例中默認並未啓用AuthorizationCache
 28      * 我的感受若使用了Spring3.1開始提供的ConcurrentMapCache支持,則可靈活決定是否啓用AuthorizationCache
 29      * 好比說這裏從數據庫獲取權限信息時,先去訪問Spring3.1提供的緩存,而不使用Shior提供的AuthorizationCache
 30      * -----------------------------------------------------------------------------------------------
 31      */
 32     @Override
 33     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){
 34         //獲取當前登陸的用戶名
 35         String currentUsername = (String)super.getAvailablePrincipal(principals);
 36         
 37 /*        UsernamePasswordToken token = new UsernamePasswordToken(currentUsername, "admin");
 38         SecurityUtils.getSubject().login(token);*/
 39         
 40         ////從數據庫中獲取當前登陸用戶的詳細信息
 41         //List<String> roleList = new ArrayList<String>();
 42         //List<String> permissionList = new ArrayList<String>();
 43         //User user = userService.getByUsername(currentUsername);
 44         //if(null != user){
 45         //    //實體類User中包含有用戶角色的實體類信息
 46         //    if(null!=user.getRoles() && user.getRoles().size()>0){
 47         //        //獲取當前登陸用戶的角色
 48         //        for(Role role : user.getRoles()){
 49         //            roleList.add(role.getName());
 50         //            //實體類Role中包含有角色權限的實體類信息
 51         //            if(null!=role.getPermissions() && role.getPermissions().size()>0){
 52         //                //獲取權限
 53         //                for(Permission pmss : role.getPermissions()){
 54         //                    if(StringUtils.isNotBlank(pmss.getPermission())){
 55         //                        permissionList.add(pmss.getPermission());
 56         //                    }
 57         //                }
 58         //            }
 59         //        }
 60         //    }
 61         //}else{
 62         //    throw new AuthorizationException();
 63         //}
 64         ////爲當前用戶設置角色和權限
 65         //SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
 66         //simpleAuthorInfo.addRoles(roleList);
 67         //simpleAuthorInfo.addStringPermissions(permissionList);
 68         //實際中可能會像上面註釋的那樣,從數據庫或緩存中取得用戶的角色和權限信息
 69         SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
 70         if(null!=currentUsername && "admin".equals(currentUsername)){
 71             //添加一個角色,不是配置意義上的添加,而是證實該用戶擁有admin角色
 72             simpleAuthorInfo.addRole("admin");
 73             simpleAuthorInfo.addRole("user");
 74             //添加權限
 75             //simpleAuthorInfo.addStringPermission("admin:manage");
 76             //simpleAuthorInfo.addStringPermission("admin:add");
 77             simpleAuthorInfo.addStringPermission("*");//擁有全部權限
 78             System.out.println("已爲用戶[jadyer]賦予了[admin]角色和[admin:manage]權限");
 79             return simpleAuthorInfo;
 80         }
 81         if(null!=currentUsername && "fangke".equals(currentUsername)){
 82             System.out.println("當前用戶[xuanyu]無受權(不須要爲其賦予角色和權限)");
 83             return simpleAuthorInfo;
 84         }
 85         //若該方法什麼都不作直接返回null的話
 86         //就會致使任何用戶訪問/admin/listUser.jsp時都會自動跳轉到unauthorizedUrl指定的地址
 87         //詳見applicationContext.xml中的<bean id="shiroFilter">的配置
 88         return null;
 89     }
 90 
 91     /**
 92      * 驗證當前登陸的Subject
 93      * 經測試:本例中該方法的調用時機爲LoginController.login()方法中執行Subject.login()的時候
 94      */
 95     @Override
 96     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
 97         //獲取基於用戶名和密碼的令牌
 98         //實際上這個authcToken是從LoginController裏面currentUser.login(token)傳過來的
 99         //兩個token的引用都是同樣的,本例中是:org.apache.shiro.authc.UsernamePasswordToken@33799a1e
100         UsernamePasswordToken token = (UsernamePasswordToken)authcToken;
101         System.out.print("驗證當前Subject時獲取到token:");
102         System.out.println(ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));
103         //User user = userService.getByUsername(token.getUsername());
104         //if(null != user){
105         //    String username = user.getUsername();
106         //    String password = user.getPassword();
107         //    String nickname = user.getNickname();
108         //    AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(username, password, nickname);
109         //    this.setSession("currentUser", user);
110         //    return authcInfo;
111         //}else{
112         //    return null;
113         //}
114         //此處無需比對,比對的邏輯Shiro會作,咱們只需返回一個和令牌相關的正確的驗證信息
115         //說白了就是第一個參數填登陸用戶名,第二個參數填合法的登陸密碼(能夠是從數據庫中取到的,本例中爲了演示就硬編碼了)
116         //這樣一來,在隨後的登陸頁面上就只有這裏指定的用戶和密碼才能經過驗證
117         if("admin".equals(token.getUsername())){
118             AuthenticationInfo authcInfo = new SimpleAuthenticationInfo("admin", "admin", this.getName());
119             this.setAuthenticationSession("admin");
120             return authcInfo;
121         }
122         if("user".equals(token.getUsername())){
123             AuthenticationInfo authcInfo = new SimpleAuthenticationInfo("user", "user", this.getName());
124             this.setAuthenticationSession("user");
125             return authcInfo;
126         }
127         //沒有返回登陸用戶名對應的SimpleAuthenticationInfo對象時,就會在LoginController中拋出UnknownAccountException異常
128         return null;
129     }
130 
131     /**
132      * 將一些數據放到ShiroSession中,以便於其它地方使用
133      * 好比Controller裏面,使用時直接用HttpSession.getAttribute(key)就能夠取到
134      */
135     private void setAuthenticationSession(Object value){
136         Subject currentUser = SecurityUtils.getSubject();
137         if(null != currentUser){
138             Session session = currentUser.getSession();
139             System.out.println("當前Session超時時間爲[" + session.getTimeout() + "]毫秒");//web.xml未配置session時間默認30分鐘,配置了按照實際配置爲準
140             session.setTimeout(1000 * 60 * 60 * 2);
141            // session.setTimeout(1000 * 60);//用戶操做時時間順延
142             System.out.println("修改Session超時時間爲[" + session.getTimeout() + "]毫秒");
143             session.setAttribute("currentUser", value);
144         }
145     }
146 }
View Code

 

Realm中實現兩個方法:apache

doGetAuthorizationInfo只要訪問須要受權的內容,都會進入此方法,查找當前登陸用戶的權限api

doGetAuthenticationInfo調用shiro登陸時,會執行此方法spring-mvc

 

shiro有三種攔截方式,

第一種是xml配置

第二種是註解,我我的比較喜歡使用註解方式,感受這樣配置有針對性

第三種是頁面攔截,這種沒有寫,由於比較簡單,百度一下全都有了

 

 

本內容參考如下學習總結,感謝。http://jadyer.cn/2013/09/30/springmvc-shiro/

相關文章
相關標籤/搜索