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>
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>
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>
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>
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 }
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 }
Realm中實現兩個方法:apache
doGetAuthorizationInfo只要訪問須要受權的內容,都會進入此方法,查找當前登陸用戶的權限api
doGetAuthenticationInfo調用shiro登陸時,會執行此方法spring-mvc
shiro有三種攔截方式,
第一種是xml配置
第二種是註解,我我的比較喜歡使用註解方式,感受這樣配置有針對性
第三種是頁面攔截,這種沒有寫,由於比較簡單,百度一下全都有了
本內容參考如下學習總結,感謝。http://jadyer.cn/2013/09/30/springmvc-shiro/