鍍金池/ 教程/ Java/ 初體驗
初體驗
權(quán)限鑒定基礎(chǔ)
Remember-Me 功能
匿名認(rèn)證
intercept-url配置
認(rèn)證簡介
退出登錄 logout
AuthenticationProvider
Filter
關(guān)于登錄
異常信息本地化
緩存 UserDetails
session 管理
核心類簡介

初體驗

首先我們?yōu)?Spring Security 專門建立一個 Spring 的配置文件,該文件就專門用來作為 Spring Security 的配置。使用 Spring Security 我們需要引入 Spring Security 的 NameSpace。

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:security="http://www.springframework.org/schema/security"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/security
          http://www.springframework.org/schema/security/spring-security-3.1.xsd">

</beans>

Spring Security 命名空間的引入可以簡化我們的開發(fā),它涵蓋了大部分 Spring Security 常用的功能。它的設(shè)計是基于框架內(nèi)大范圍的依賴的,可以被劃分為以下幾塊。

  • Web/Http 安全:這是最復(fù)雜的部分。通過建立 filter 和相關(guān)的 service bean 來實現(xiàn)框架的認(rèn)證機制。當(dāng)訪問受保護的 URL 時會將用戶引入登錄界面或者是錯誤提示界面。
  • 業(yè)務(wù)對象或者方法的安全:控制方法訪問權(quán)限的。
  • AuthenticationManager:處理來自于框架其他部分的認(rèn)證請求。
  • AccessDecisionManager:為 Web 或方法的安全提供訪問決策。會注冊一個默認(rèn)的,但是我們也可以通過普通 bean 注冊的方式使用自定義的 AccessDecisionManager。
  • AuthenticationProvider:AuthenticationManager 是通過它來認(rèn)證用戶的。
  • UserDetailsService:跟 AuthenticationProvider 關(guān)系密切,用來獲取用戶信息的。

引入了 Spring Security 的 NameSpace 之后我們就可以使用該命名空間下的元素來配置 Spring Security 了。首先我們來定義一個 http 元素,security 只是我們使用命名空間的一個前綴。http 元素是用于定義 Web 相關(guān)權(quán)限控制的。

   <security:http auto-config="true">
      <security:intercept-url pattern="/**" access="ROLE_USER"/>
   </security:http> 

如上定義中,intercept-url 定義了一個權(quán)限控制的規(guī)則。pattern 屬性表示我們將對哪些 url 進行權(quán)限控制,其也可以是一個正則表達式,如上的寫法表示我們將對所有的 URL 進行權(quán)限控制;access 屬性表示在請求對應(yīng)的 URL 時需要什么權(quán)限,默認(rèn)配置時它應(yīng)該是一個以逗號分隔的角色列表,請求的用戶只需擁有其中的一個角色就能成功訪問對應(yīng)的 URL。這里的 “ROLE_USER” 表示請求的用戶應(yīng)當(dāng)具有 ROLEUSER 角色?!癛OLE” 前綴是一個提示 Spring 使用基于角色的檢查的標(biāo)記。

有了權(quán)限控制的規(guī)則了后,接下來我們需要定義一個 AuthenticationManager 用于認(rèn)證。我們先來看如下定義:

   <security:authentication-manager>
      <security:authentication-provider>
         <security:user-service>
            <security:user name="user" password="user" authorities="ROLE_USER"/>
            <security:user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN"/>
         </security:user-service>
      </security:authentication-provider>
   </security:authentication-manager>

authentication-manager 元素指定了一個 AuthenticationManager,其需要一個 AuthenticationProvider(對應(yīng) authentication-provider 元素)來進行真正的認(rèn)證,默認(rèn)情況下 authentication-provider 對應(yīng)一個 DaoAuthenticationProvider,其需要 UserDetailsService(對應(yīng) user-service 元素)來獲取用戶信息 UserDetails(對應(yīng) user 元素)。這里我們只是簡單的使用 user 元素來定義用戶,而實際應(yīng)用中這些信息通常都是需要從數(shù)據(jù)庫等地方獲取的,這個將放到后續(xù)再講。我們可以看到通過 user 元素我們可以指定 user 對應(yīng)的用戶名、密碼和擁有的權(quán)限。user-service 還支持通過 properties 文件來指定用戶信息,如:

   <security:user-service properties="/WEB-INF/config/users.properties"/>

其中屬性文件應(yīng)遵循如下格式:

username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]

所以,對應(yīng)上面的配置文件,我們的 users.properties 文件的內(nèi)容應(yīng)該如下所示:

#username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
user=user,ROLE_USER
admin=admin,ROLE_USER,ROLE_ADMIN

至此,我們的 Spring Security 配置文件的配置就完成了。完整配置文件將如下所示。

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:security="http://www.springframework.org/schema/security"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/security
          http://www.springframework.org/schema/security/spring-security-3.1.xsd">

   <security:http auto-config="true">
      <security:intercept-url pattern="/**" access="ROLE_USER"/>
   </security:http>    

   <security:authentication-manager>
      <security:authentication-provider>
         <security:user-service>
            <security:user name="user" password="user" authorities="ROLE_USER"/>
            <security:user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN"/>
         </security:user-service>
      </security:authentication-provider>
   </security:authentication-manager>

</beans>

之后我們告訴 Spring 加載這個配置文件。通常,我們可以在 web.xml 文件中通過 context-param 把它指定為 Spring 的初始配置文件,也可以在對應(yīng) Spring 的初始配置文件中引入它。這里我們采用前者。

   <context-param>
      <param-name>contextConfigLocation</param-name>
   <param-value>/WEB-INF/config/applicationContext.xml,/WEB-INF/config/spring-security.xml</param-value>
   </context-param>

   <listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>

Spring 的配置文件是通過對應(yīng)的 ContextLoaderListener 來加載和初始化的,上述代碼中的 applicationContext.xml 文件就是對應(yīng)的 Spring 的配置文件,如果沒有可以不用配置。接下來我們還需要在 web.xml 中定義一個 filter 用來攔截需要交給 Spring Security 處理的請求,需要注意的是該 filter 一定要定義在其它如 SpringMVC 等攔截請求之前。這里我們將攔截所有的請求,具體做法如下所示:

   <filter>
      <filter-name>springSecurityFilterChain</filter-name>
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
   </filter>
   <filter-mapping>
      <filter-name>springSecurityFilterChain</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>

接下來可以啟動我們的應(yīng)用,然后在瀏覽器中訪問我們的主頁。你會看到如下頁面。

http://wiki.jikexueyuan.com/project/spring-security/images/1.png" alt="" />

因為我們的 spring-security.xml 文件中配置好了所有的請求都需要 “ROLE_USER” 權(quán)限,所以當(dāng)我們在請求主頁的時候,Spring Security 發(fā)現(xiàn)我們還沒有登錄,Spring 會引導(dǎo)我們到登錄界面。使用正確的用戶名和密碼(如上面配置的 user/user 或 admin/admin)登錄后,如果符合對應(yīng)的權(quán)限我們就可以訪問主頁了,否則將出現(xiàn) 403(禁止訪問)界面。

可能你會奇怪,我們沒有建立上面的登錄頁面,為什么 Spring Security 會跳到上面的登錄頁面呢?這是我們設(shè)置 http 的 auto-config=”true” 時 Spring Security 自動為我們生成的。

當(dāng)指定 http 元素的 auto-config=”true” 時,就相當(dāng)于如下內(nèi)容的簡寫。

   <security:http>
      <security:form-login/>
      <security:http-basic/>
      <security:logout/>
   </security:http>

這些元素負(fù)責(zé)建立表單登錄、基本的認(rèn)證和登出處理。它們都可以通過指定對應(yīng)的屬性來改變它們的行為。