1. 程式人生 > >Spring+Shiro案例分析

Spring+Shiro案例分析

在 Web 專案中應用 Apache Shiro

Apache Shiro 是功能強大並且容易整合的開源許可權框架,它能夠完成認證、授權、加密、會話管理等功能。認證和授權為許可權控制的核心,簡單來說,“認證”就是證明你是誰? Web 應用程式一般做法通過表單提交使用者名稱及密碼達到認證目的。“授權”即是否允許已認證使用者訪問受保護資源。關於 Shiro 的一系列特徵及優點,很多文章已有列舉,這裡不再逐一贅述,本文重點介紹 Shiro 在 Web Application 中如何實現驗證碼認證以及如何實現單點登入。

使用者許可權模型

在揭開 Shiro 面紗之前,我們需要認知使用者許可權模型。本文所提到使用者許可權模型,指的是用來表達使用者資訊及使用者許可權資訊的資料模型。即能證明“你是誰?”、“你能訪問多少受保護資源?”。為實現一個較為靈活的使用者許可權資料模型,通常把使用者資訊單獨用一個實體表示,使用者許可權資訊用兩個實體表示。

  1. 使用者資訊用 LoginAccount 表示,最簡單的使用者資訊可能只包含使用者名稱 loginName 及密碼 password 兩個屬性。實際應用中可能會包含使用者是否被禁用,使用者資訊是否過期等資訊。
  2. 使用者許可權資訊用 Role 與 Permission 表示,Role 與 Permission 之間構成多對多關係。Permission 可以理解為對一個資源的操作,Role 可以簡單理解為 Permission 的集合。
  3. 使用者資訊與 Role 之間構成多對多關係。表示同一個使用者可以擁有多個 Role,一個 Role 可以被多個使用者所擁有。
圖 1. 使用者許可權模型
圖 1. 使用者許可權模型

認證與授權

Shiro 認證與授權處理過程

  • 被 Shiro 保護的資源,才會經過認證與授權過程。使用 Shiro 對 URL 進行保護可以參見“與 Spring 整合”章節。
  • 使用者訪問受 Shiro 保護的 URL;例如 http://host/security/action.do。
  • Shiro 首先檢查使用者是否已經通過認證,如果未通過認證檢查,則跳轉到登入頁面,否則進行授權檢查。認證過程需要通過 Realm 來獲取使用者及密碼資訊,通常情況我們實現 JDBC Realm,此時使用者認證所需要的資訊從資料庫獲取。如果使用了快取,除第一次外使用者資訊從快取獲取。
  • 認證通過後接受 Shiro 授權檢查,授權檢查同樣需要通過 Realm 獲取使用者許可權資訊。Shiro 需要的使用者許可權資訊包括 Role 或 Permission,可以是其中任何一種或同時兩者,具體取決於受保護資源的配置。如果使用者許可權資訊未包含 Shiro 需要的 Role 或 Permission,授權不通過。只有授權通過,才可以訪問受保護 URL 對應的資源,否則跳轉到“未經授權頁面”。

Shiro Realm

在 Shiro 認證與授權處理過程中,提及到 Realm。Realm 可以理解為讀取使用者資訊、角色及許可權的 DAO。由於大多 Web 應用程式使用了關係資料庫,因此實現 JDBC Realm 是常用的做法,後面會提到 CAS Realm,另一個 Realm 的實現。

清單 1. 實現自己的 JDBC Realm
 public class MyShiroRealm extends AuthorizingRealm{ 
   
   // 用於獲取使用者資訊及使用者許可權資訊的業務介面
   private BusinessManager businessManager; 
    
   // 獲取授權資訊
   protected AuthorizationInfo doGetAuthorizationInfo( 
      PrincipalCollection principals) { 
      String username = (String) principals.fromRealm( 
         getName()).iterator().next(); 
      
      if( username != null ){ 
      // 查詢使用者授權資訊
         Collection<String> pers=businessManager.queryPermissions(username); 
         if( pers != null && !pers.isEmpty() ){ 
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 
            for( String each:pers ) 
               info.addStringPermissions( each ); 
            
            return info; 
         } 
      } 
      
      return null; 
   } 
   
   // 獲取認證資訊
   protected AuthenticationInfo doGetAuthenticationInfo( 
      AuthenticationToken authcToken ) throws AuthenticationException { 
      UsernamePasswordToken token = (UsernamePasswordToken) authcToken; 
      // 通過表單接收的使用者名稱
      String username = token.getUsername(); 
      
      if( username != null && !"".equals(username) ){ 
         LoginAccount account = businessManager.get( username ); 
         
         if( account != null ){ 
            return new SimpleAuthenticationInfo( 
               account.getLoginName(),account.getPassword(),getName() ); 
         } 
      } 
      
      return null; 
   } 
 }

程式碼說明:

  1. businessManager 表示從資料庫獲取使用者資訊及使用者許可權資訊的業務類,實際情況中可能因使用者許可權模型設計不同或持久化框架選擇不同,這裡沒給出示例程式碼。
  2. doGetAuthenticationInfo 方法,取使用者資訊。對照使用者許可權模型來說,就是取 LoginAccount 實體。最終我們需要為 Shiro 提供 AuthenticationInfo 物件。
  3. doGetAuthorizationInfo 方法,獲取使用者許可權資訊。程式碼給出了獲取使用者 Permission 的示例,獲取使用者 Role 的程式碼類似。為 Shiro 提供的使用者許可權資訊以 AuthorizationInfo 物件形式返回。

為何對 Shiro 情有獨鍾

或許有人要問,我一直在使用 Spring,應用程式的安全元件早已選擇了 Spring Security,為什麼還需要 Shiro ?當然,不可否認 Spring Security 也是一款優秀的安全控制組件。本文的初衷不是讓您必須選擇 Shiro 以及必須放棄 Spring Security,秉承客觀的態度,下面對兩者略微比較:

  1. 簡單性,Shiro 在使用上較 Spring Security 更簡單,更容易理解。
  2. 靈活性,Shiro 可執行在 Web、EJB、IoC、Google App Engine 等任何應用環境,卻不依賴這些環境。而 Spring Security 只能與 Spring 一起整合使用。
  3. 可插拔,Shiro 乾淨的 API 和設計模式使它可以方便地與許多的其它框架和應用進行整合。Shiro 可以與諸如 Spring、Grails、Wicket、Tapestry、Mule、Apache Camel、Vaadin 這類第三方框架無縫整合。Spring Security 在這方面就顯得有些捉衿見肘。

與 Spring 整合

在 Java Web Application 開發中,Spring 得到了廣泛使用;與 EJB 相比較,可以說 Spring 是主流。Shiro 自身提供了與 Spring 的良好支援,在應用程式中整合 Spring 十分容易。

有了前面提到的使用者許可權資料模型,並且實現了自己的 Realm,我們就可以開始整合 Shiro 為應用程式服務了。

Shiro 的安裝

Shiro 的安裝非常簡單,在 Shiro 官網下載 shiro-all-1.2.0.jar、shiro-cas-1.2.0.jar(單點登入需要),及 SLF4J 官網下載 Shiro 依賴的日誌元件 slf4j-api-1.6.1.jar。Spring 相關的 JAR 包這裡不作列舉。這些 JAR 包需要放置到 Web 工程 /WEB-INF/lib/ 目錄。至此,剩下的就是配置了。

配置過濾器

首先,配置過濾器讓請求資源經過 Shiro 的過濾處理,這與其它過濾器的使用類似。

清單 2. web.xml 配置
 <filter> 
   <filter-name>shiroFilter</filter-name> 
   <filter-class> 
      org.springframework.web.filter.DelegatingFilterProxy 
   </filter-class> 
 </filter> 
 <filter-mapping> 
   <filter-name>shiroFilter</filter-name> 
   <url-pattern>/*</url-pattern> 
 </filter-mapping>

Spring 配置

接下來僅僅配置一系列由 Spring 容器管理的 Bean,整合大功告成。各個 Bean 的功能見程式碼說明。

清單 3. Spring 配置
 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> 
   <property name="securityManager" ref="securityManager"/> 
   <property name="loginUrl" value="/login.do"/> 
   <property name="successUrl" value="/welcome.do"/> 
   <property name="unauthorizedUrl" value="/403.do"/> 
   <property name="filters"> 
      <util:map> 
         <entry key="authc" value-ref="formAuthenticationFilter"/> 
      </util:map> 
   </property> 
   <property name="filterChainDefinitions"> 
      <value> 
         /=anon 
         /login.do*=authc 
         /logout.do*=anon 
         
         # 許可權配置示例
         /security/account/view.do=authc,perms[SECURITY_ACCOUNT_VIEW] 
         
         /** = authc 
      </value> 
   </property> 
 </bean> 

 <bean id="securityManager" 
   class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> 
   <property name="realm" ref="myShiroRealm"/> 
 </bean> 

 <bean id="myShiroRealm" class="xxx.packagename.MyShiroRealm"> 
   <!-- businessManager 用來實現使用者名稱密碼的查詢 --> 
   <property name="businessManager" ref="businessManager"/> 
   <property name="cacheManager" ref="shiroCacheManager"/> 
 </bean> 

 <bean id="lifecycleBeanPostProcessor" 
    class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> 

 <bean id="shiroCacheManager" 
   class="org.apache.shiro.cache.ehcache.EhCacheManager"> 
   <property name="cacheManager" ref="cacheManager"/> 
 </bean> 

 <bean id="formAuthenticationFilter" 
   class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter"/>

程式碼說明:

  1. shiroFilter 中 loginUrl 為登入頁面地址,successUrl 為登入成功頁面地址(如果首先訪問受保護 URL 登入成功,則跳轉到實際訪問頁面),unauthorizedUrl 認證未通過訪問的頁面(前面提到的“未經授權頁面”)。
  2. shiroFilter 中 filters 屬性,formAuthenticationFilter 配置為基於表單認證的過濾器。
  3. shiroFilter 中 filterChainDefinitions 屬性,anon 表示匿名訪問(不需要認證與授權),authc 表示需要認證,perms[SECURITY_ACCOUNT_VIEW] 表示使用者需要提供值為“SECURITY_ACCOUNT_VIEW”Permission 資訊。由此可見,連線地址配置為 authc 或 perms[XXX] 表示為受保護資源。
  4. securityManager 中 realm 屬性,配置為我們自己實現的 Realm。關於 Realm,參見前面“Shiro Realm”章節。
  5. myShiroRealm 為我們自己需要實現的 Realm 類,為了減小資料庫壓力,添加了快取機制。
  6. shiroCacheManager 是 Shiro 對快取框架 EhCache 的配置。

實現驗證碼認證

驗證碼是有效防止暴力破解的一種手段,常用做法是在服務端產生一串隨機字串與當前使用者會話關聯(我們通常說的放入 Session),然後向終端使用者展現一張經過“擾亂”的圖片,只有當用戶輸入的內容與服務端產生的內容相同時才允許進行下一步操作。

產生驗證碼

作為演示,我們選擇開源的驗證碼元件 kaptcha。這樣,我們只需要簡單配置一個 Servlet,頁面通過 IMG 標籤就可以展現圖形驗證碼。

清單 4. web.xml 配置
 <!-- captcha servlet--> 
 <servlet> 
   <servlet-name>kaptcha</servlet-name> 
   <servlet-class> 
      com.google.code.kaptcha.servlet.KaptchaServlet 
   </servlet-class> 
 </servlet> 
 <servlet-mapping> 
 <servlet-name>kaptcha</servlet-name> 
 <url-pattern>/images/kaptcha.jpg</url-pattern> 
 </servlet-mapping>

擴充套件 UsernamePasswordToken

Shiro 表單認證,頁面提交的使用者名稱密碼等資訊,用 UsernamePasswordToken 類來接收,很容易想到,要接收頁面驗證碼的輸入,我們需要擴充套件此類:

清單 5. CaptchaUsernamePasswordToken
 public class CaptchaUsernamePasswordToken extends UsernamePasswordToken{ 

 private String captcha; 

 // 省略 getter 和 setter 方法

 public CaptchaUsernamePasswordToken(String username, char[] password, 
 boolean rememberMe, String host,String captcha) { 
 super(username, password, rememberMe, host); 
 this.captcha = captcha; 
 } 
 }

擴充套件 FormAuthenticationFilter

接下來我們擴充套件 FormAuthenticationFilter 類,首先覆蓋 createToken 方法,以便獲取 CaptchaUsernamePasswordToken 例項;然後增加驗證碼校驗方法 doCaptchaValidate;最後覆蓋 Shiro 的認證方法 executeLogin,在原表單認證邏輯處理之前進行驗證碼校驗。

清單 6. CaptchaUsernamePasswordToken
 public class CaptchaFormAuthenticationFilter extends FormAuthenticationFilter{ 

   public static final String DEFAULT_CAPTCHA_PARAM = "captcha"; 
   
   private String captchaParam = DEFAULT_CAPTCHA_PARAM; 
   
   public String getCaptchaParam() { 
      return captchaParam; 
   } 
   
   public void setCaptchaParam(String captchaParam) { 
      this.captchaParam = captchaParam; 
   } 
   
   protected String getCaptcha(ServletRequest request) { 
      return WebUtils.getCleanParam(request, getCaptchaParam()); 
   } 
   
   // 建立 Token 
   protected CaptchaUsernamePasswordToken createToken( 
      ServletRequest request, ServletResponse response) { 
   
      String username = getUsername(request); 
      String password = getPassword(request); 
      String captcha = getCaptcha(request); 
      boolean rememberMe = isRememberMe(request); 
      String host = getHost(request); 
                   
      return new CaptchaUsernamePasswordToken( 
         username, password, rememberMe, host,captcha); 
   } 
   
   // 驗證碼校驗
   protected void doCaptchaValidate( HttpServletRequest request 
      ,CaptchaUsernamePasswordToken token ){ 

      String captcha = (String)request.getSession().getAttribute( 
         com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); 
      
      if( captcha!=null && 
         !captcha.equalsIgnoreCase(token.getCaptcha()) ){ 
         throw new IncorrectCaptchaException ("驗證碼錯誤!"); 
      } 
   } 
    
   // 認證
   protected boolean executeLogin(ServletRequest request, 
      ServletResponse response) throws Exception { 
      CaptchaUsernamePasswordToken token = createToken(request, response); 
       
      try { 
         doCaptchaValidate( (HttpServletRequest)request,token ); 
                 
         Subject subject = getSubject(request, response); 
         subject.login(token); 
                     
         return onLoginSuccess(token, subject, request, response); 
      } catch (AuthenticationException e) { 
         return onLoginFailure(token, e, request, response); 
      } 
   } 

 }

程式碼說明:

  1. 新增 captchaParam 變數,為的是頁面表單提交驗證碼的引數名可以進行靈活配置。
  2. doCaptchaValidate 方法中,驗證碼校驗使用了框架 KAPTCHA 所提供的 API。

新增 IncorrectCaptchaException

前面驗證碼校驗不通過,我們丟擲一個異常 IncorrectCaptchaException,此類繼承 AuthenticationException,之所以需要擴充套件一個新的異常類,為的是在頁面能更精準顯示錯誤提示資訊。

清單 7. IncorrectCaptchaException
 public class IncorrectCaptchaException extends AuthenticationException{ 
   
   public IncorrectCaptchaException() { 
      super(); 
   } 
   
   public IncorrectCaptchaException(String message, Throwable cause) { 
      super(message, cause); 
   } 
   
   public IncorrectCaptchaException(String message) { 
      super(message); 
   } 
   
   public IncorrectCaptchaException(Throwable cause) { 
      super(cause); 
   } 
 }

頁面展現驗證碼錯誤提示資訊

清單 8. 頁面認證錯誤資訊展示
 Object obj=request.getAttribute( 
   org.apache.shiro.web.filter.authc.FormAuthenticationFilter 
      .DEFAULT_ERROR_KEY_ATTRIBUTE_NAME); 
 AuthenticationException authExp = (AuthenticationException)obj; 
 if( authExp != null ){ 
   String expMsg=""; 
   
   if(authExp instanceof UnknownAccountException || 
      authExp instanceof IncorrectCredentialsException){ 
      expMsg="錯誤的使用者賬號或密碼!"; 
   }else if( authExp instanceof IncorrectCaptchaException){ 
      expMsg="驗證碼錯誤!"; 
   }else{ 
      expMsg="登入異常 :"+authExp.getMessage() ; 
   } 
    
   out.print("<div class=\"error\">"+expMsg+"</div>"); 
 }

實現單點登入

前面章節,我們認識了 Shiro 的認證與授權,並結合 Spring 作了整合實現。現實中,有這樣一個場景,我們擁有很多業務系統,按照前面的思路,如果訪問每個業務系統,都要進行認證,這樣是否有點難讓人授受。有沒有一種機制,讓我們只認證一次,就可以任意訪問目標系統呢?

上面的場景,就是我們常提到的單點登入 SSO。Shiro 從 1.2 版本開始對 CAS 進行支援,CAS 就是單點登入的一種實現。

Shiro CAS 認證流程

  • 使用者首次訪問受保護的資源;例如 http://casclient/security/view.do
  • 由於未通過認證,Shiro 首先把請求地址(http://casclient/security/view.do)快取起來。
  • 然後跳轉到 CAS 伺服器進行登入認證,在 CAS 服務端認證完成後需要返回到請求的 CAS 客戶端,因此在請求時,必須在引數中新增返回地址 ( 在 Shiro 中名為 CAS Service)。 例如 http://casserver/login?service=http://casclient/shiro-cas
  • 由 CAS 伺服器認證通過後,CAS 伺服器為返回地址新增 ticket。例如 http://casclient/shiro-cas?ticket=ST-4-BWMEnXfpxfVD2jrkVaLl-cas
  • 接下來,Shiro 會校驗 ticket 是否有效。由於 CAS 客戶端不提供直接認證,所以 Shiro 會向 CAS 服務端發起 ticket 校驗檢查,只有服務端返回成功時,Shiro 才認為認證通過。
  • 認證通過,進入授權檢查。Shiro 授權檢查與前面提到的相同。
  • 最後授權檢查通過,使用者正常訪問到 http://casclient/security/view.do。

CAS Realm

Shiro 提供了一個名為 CasRealm 的類,與前面提到的 JDBC Realm 相似,該類同樣包括認證和授權兩部分功能。認證就是校驗從 CAS 服務端返回的 ticket 是否有效;授權還是獲取使用者許可權資訊。

實現單點登入功能,需要擴充套件 CasRealm 類。

清單 9. Shiro CAS Realm
 public class MyCasRealm extends CasRealm{ 
   
   // 獲取授權資訊
   protected AuthorizationInfo doGetAuthorizationInfo( 
      PrincipalCollection principals) { 
      //... 與前面 MyShiroRealm 相同
   } 
   
    public String getCasServerUrlPrefix() { 
      return "http://casserver/login"; 
   } 
   
   public String getCasService() { 
      return "http://casclient/shiro-cas"; 
   } 
   16 
 }

程式碼說明:

  1. doGetAuthorizationInfo 獲取授權資訊與前面章節“實現自己的 JDBC Realm”相同。
  2. 認證功能由 Shiro 自身提供的 CasRealm 實現。
  3. getCasServerUrlPrefix 方法返回 CAS 伺服器地址,實際使用一般通過引數進行配置。
  4. getCasService 方法返回 CAS 客戶端處理地址,實際使用一般通過引數進行配置。
  5. 認證過程需 keystore,否則會出現異常。可以通過設定系統屬性的方式來指定,例如 System.setProperty("javax.net.ssl.trustStore","keystore-file");

CAS Spring 配置

實現單點登入的 Spring 配置與前面類似,不同之處參見程式碼說明。

清單 10. Shiro CAS Spring 配置
 <bean id="shiroFilter" 
   class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> 
   <property name="securityManager" ref="securityManager"/> 
   <property name="loginUrl" 
      value="http://casserver/login?service=http://casclient/shiro-cas"/> 
   <property name="successUrl" value="/welcome.do"/> 
   <property name="unauthorizedUrl" value="/403.do"/> 
   <property name="filters"> 
      <util:map> 
         <entry key="authc" value-ref="formAuthenticationFilter"/> 
         <entry key="cas" value-ref="casFilter"/> 
      </util:map> 
   </property> 
   <property name="filterChainDefinitions"> 
      <value> 
         /shiro-cas*=cas 
         /logout.do*=anon 
         /casticketerror.do*=anon 
          
         # 許可權配置示例
         /security/account/view.do=authc,perms[SECURITY_ACCOUNT_VIEW] 
          
         /** = authc 
      </value> 
   </property> 
 </bean> 
 
 <bean id="securityManager" 
   class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> 
   <property name="realm" ref="myShiroRealm"/> 
 </bean> 

 <bean id="lifecycleBeanPostProcessor" 
   class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> 

 <!-- CAS Realm --> 
 <bean id="myShiroRealm" class="xxx.packagename.MyCasRealm"> 
   <property name="cacheManager" ref="shiroCacheManager"/> 
 </bean> 

 <bean id="shiroCacheManager" 
   class="org.apache.shiro.cache.ehcache.EhCacheManager"> 
   <property name="cacheManager" ref="cacheManager"/> 
 </bean> 

 <bean id="formAuthenticationFilter" 
   class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter"/> 

 <!-- CAS Filter --> 
 <bean id="casFilter" class="org.apache.shiro.cas.CasFilter"> 
   <property name="failureUrl" value="casticketerror.do"/> 
 </bean>

程式碼說明:

  1. shiroFilter 中 loginUrl 屬性,為登入 CAS 服務端地址,引數 service 為服務端的返回地址。
  2. myShiroRealm 為上一節提到的 CAS Realm。
  3. casFilter 中 failureUrl 屬性,為 Ticket 校驗不通過時展示的錯誤頁面。

Spring + Shiro 案例詳解


專案包圖:

web.xml關鍵配置

<context-param> 
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/applicationContext.xml
/WEB-INF/classes/spring-shiro.xml
</param-value> 
</context-param>

spring-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:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"  
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
    http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<description>Shiro 配置</description>

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login.jsp" />
<property name="successUrl" value="/login.jsp" />
<property name="unauthorizedUrl" value="/error/noperms.jsp" />

<property name="filterChainDefinitions">
<value>
/login.jsp* = anon
/login.do* = anon
/index.jsp*= anon
/error/noperms.jsp*= anon
/*.jsp* = authc
/*.do* = authc
</value>
</property>
</bean>

<bean id="monitorRealm" class="com.shiro.security.MonitorRealm">
  <property name="credentialsMatcher">
           <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
               <property name="hashAlgorithmName" value="MD5"/>
             <!--   true means hex encoded, false means base64 encoded -->
               <property name="storedCredentialsHexEncoded" value="true"/>
               <!-- 迭代次數 -->
               <property name="hashIterations" value="2" />
           </bean>
          </property> 
</bean>

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 基於ehCache來快取使用者認證資訊和授權資訊的實現 -->
 <property name="cacheManager" ref="cacheManager"/>
<!-- sessionMode引數設定為native時,那麼shrio就將使用者的基本認證資訊儲存到預設名稱為shiro-activeSessionCache 的Cache中 -->
        <property name="sessionMode" value="native" />
<!--設定自定義realm -->
<property name="realm" ref="monitorRealm" />
</bean>

    
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManager" ref="ehCacheManager"/>
   <property name="cacheManagerConfigFile" value="classpath:shiro_ehcache.xml"/> 
    </bean>


<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>




<!-- securityManager -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager" />
<property name="arguments" ref="securityManager" />
</bean>

<!-- 保證實現了Shiro內部lifecycle函式的bean執行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

<!-- AOP式方法級許可權檢查  -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />

<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>

</beans>

MonitorRealm.java

package com.shiro.security;


import java.util.ArrayList;
import java.util.List;


import org.apache.shiro.authc.AccountException;
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.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;


import com.shiro.mapper.RoleMapper;
import com.shiro.mapper.UserMapper;
import com.shiro.model.Resc;
import com.shiro.model.Role;


public class MonitorRealm extends AuthorizingRealm {


@Autowired

相關推薦

Spring+Shiro案例分析

在 Web 專案中應用 Apache Shiro Apache Shiro 是功能強大並且容易整合的開源許可權框架,它能夠完成認證、授權、加密、會話管理等功能。認證和授權為許可權控制的核心,簡單來說,“認證”就是證明你是誰? Web 應用程式

Spring整合Shiro做許可權控制模組詳細案例分析

1.引入Shiro的Maven依賴 <!-- Spring 整合Shiro需要的依賴 --> <dependency> <groupId>org.apache.shiro</groupId> <artifac

Spring的注入案例分析(設值注入和構造注入)

日期: 2016-7-14 內容: 學習和記錄Spring的注入內容: 一、什麼是Spring的注入: spring的注入是指在啟動spring容器載入Bean配置的時候,完成對對變數的賦值行為。

《大型網站技術架構:核心原理與案例分析》-- 讀書筆記 (5) :網購秒殺系統

案例 並發 刷新 隨機 url 對策 -- 技術 動態生成 1. 秒殺活動的技術挑戰及應對策略 1.1 對現有網站業務造成沖擊 秒殺活動具有時間短,並發訪問量大的特點,必然會對現有業務造成沖擊。對策:秒殺系統獨立部署 1.2 高並發下的應用、

VC運行庫版本不同導致鏈接.LIB靜態庫時發生重復定義問題的一個案例分析和總結

修改 borde 並且 release 鏈接 部分 sdn 托管代碼 兩個 MSDN中對於在不同的配置下Link的LIB作了說明: C Runtime Library: 開關 對應的庫 版本 /MD

OAuth2.0學習(4-11)spring-oauth-server分析 - http元素使用的是何種AuthenticationManager?

認證 lte filters -1 oauth2 authent spring src 自己 1、在加載配置文件定義時,判斷使用哪個AuthenticationManager 在配置文件Security.xml加載時,首先創建一個ProviderManager

MySQL令人頭疼的Aborted告警案例分析

mysql error got an error reading communication packetsMySQL關於aborted告警日誌的分析實戰Part1:寫在最前在MySQL的error log中,我們會經常性看到一些各類的Aborted connection錯誤,本文中會針對這類錯誤進行一個初步

案例分析之運行順序

結束 per color void 結果 方法 word pre subclass public class shunXu { private static shunXu d = new shunXu(); private SubClass t = new

POI 實現Excel 導出案例分析

poi 實現excel導出案例分析無論使用poi還是使用jxl導出excel都需要用到流一種是outputstrean,另一種fileoutputstream第一種:如果想要彈出保存的提示框必須加入下列三句response.setContentType("application/vnd.ms-excel; c

Spring源碼分析之IOC容器(一)

util 感覺 不能 end bsp initial 博文 要掌握 sof   Spring作為當今風靡世界的Web領域的第一框架,作為一名Java開發程序員是一定要掌握的,除了需要掌握基本的使用之外,更需要掌握其實現原理,因為我們往往在開發的過程中,會出現各種各樣的異常問

綜合案例分析(sort,cut,正則)

sbin ati bsp ima 如何 難點 一次 方法 當前 1、 找出ifconfig “網卡名” 命令結果中本機IPv4地址 分析: 解釋:要取出ip地址,首先我們可以先取出ip所在的行,即取行;可以結合head和tail,後面會有 更好的方法去取行,取列當然

開源項目spring-shiro-training思維導圖

權限系統 監控 get 需要 batis 緩存機制 簡介 權限控制 china 寫在前面 終於完成了一個開源項目的思維導圖解讀。選spring-shiro-training這個項目解讀是因為它開源,然後涉及到了很多我們常用的技術,如緩存,權限,任務調度,ssm框架,

java代碼實現highchart與數據庫數據結合完整案例分析(一)---餅狀圖

隱藏 des log cred 數據庫數據 idt string 時間 input 作者原創:轉載請註明出處 在做項目的過程中,經常會用到統計數據,同時會用到highchart或echart進行數據展示,highchart是外國開發的數據統計圖插件, echa

java代碼實現highchart與數據庫數據結合完整案例分析(二)---折線圖

end idt 。。 客戶端 屬性 hid pla 循環 scrip 作者原創:未經博主允許不許轉載 在上一篇的博客中,展示和分析了如何做一個餅狀圖,有疑問可以參考上一篇博客。 現在分析和展示折線圖的繪制和案例分析, 先展示效果圖: 與餅狀圖不同的是,折線圖展現更多的數據

Spring源碼分析系列】啟動component-scan類掃描加載過程

代碼段 包裝 ole 一次 設定 logs sep 列表 support 原文地址:http://blog.csdn.net/xieyuooo/article/details/9089441/ 在spring 3.0以上大家都一般會配置一個Servelet,如下所示: 1

如何拉動內需,擊中客戶深層需求,4個經典案例分析

推銷員 機器 介紹 維生素 電話銷售 -s 綜合 就會 沒有 (第三個醫患案例僅作為啟發,不倡導醫生為之,在此聲明) 導讀:客戶的需求往往是多方面的、不確定的,需要去分析和引導。客戶的需求是指通過買賣雙方的長期溝通,對客戶購買產品的欲望、用途、功能、款

APP案例分析

在哪裏 調研 產品 可能 時間 abc 觸發 之前 明顯 APP案例分析 產品:單機鬥地主(開心版) 選擇理由:這個app其實是我在回家火車上無聊偶然發現的,之前一直都是用的騰訊的歡樂鬥地主,玩兒了幾次這個單機鬥地主發現還不錯。 第一部分 調研, 評測 第一次上手體驗

個人作業2:APP案例分析

似的 第一時間 為我 style href 程序出錯 朋友 bsp oca 鐵路12306案例分析 第一部分 調研, 評測 1.下載軟件並使用起來,描述最簡單直觀的個人第一次上手體驗。 鐵路12306app第一次使用的時候讓人感覺界面簡潔明

APP案例分析之華為瀏覽器

logs es2017 感覺 尋找 nbsp 5.1 是否 華為 分析 第一部分 對華為瀏覽器的調研,評測 1、對華為瀏覽器的第一次上手體驗   我會使用華為瀏覽器呢,是因為我買的手機是華為nova,該瀏覽器也是手機裏面預裝的。剛開始用的時候也沒太註意,感覺跟以前用的其他

第二次 作業——APP案例分析

ive 滿足 電腦 截圖 哪裏 href 而在 軟件 體驗 APP案例分析 產品   網易雲課堂   選擇理由   網易雲課堂是從大一就開始使用的一款學習軟件,有海量的學習資源,很適合學生課余時間的自主學習 調研,評測   上手體驗    第一次打開網易雲課堂app