首先我們為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命名空間的引入可以簡化我們的開發,它涵蓋了大部分Spring Security常用的功能。它的設計是基於框架內大范圍的依賴的,可以被划分為以下幾塊。
- Web/Http 安全:這是最復雜的部分。通過建立filter和相關的service bean來實現框架的認證機制。當訪問受保護的URL時會將用戶引入登錄界面或者是錯誤提示界面。
- 業務對象或者方法的安全:控制方法訪問權限的。
- AuthenticationManager:處理來自於框架其他部分的認證請求。
- AccessDecisionManager:為Web或方法的安全提供訪問決策。會注冊一個默認的,但是我們也可以通過普通bean注冊的方式使用自定義的AccessDecisionManager。
- AuthenticationProvider:AuthenticationManager是通過它來認證用戶的。
- UserDetailsService:跟AuthenticationProvider關系密切,用來獲取用戶信息的。
引入了Spring Security的NameSpace之后我們就可以使用該命名空間下的元素來配置Spring Security了。首先我們來定義一個http元素,security只是我們使用命名空間的一個前綴。http元素是用於定義Web相關權限控制的。
<security:http auto-config="true">
<security:intercept-url pattern="/**" access="ROLE_USER"/>
</security:http>
如上定義中,intercept-url定義了一個權限控制的規則。pattern屬性表示我們將對哪些url進行權限控制,其也可以是一個正則表達式,如上的寫法表示我們將對所有的URL進行權限控制;access屬性表示在請求對應的URL時需要什么權限,默認配置時它應該是一個以逗號分隔的角色列表,請求的用戶只需擁有其中的一個角色就能成功訪問對應的URL。這里的“ROLE_USER”表示請求的用戶應當具有ROLE_USER角色。“ROLE_”前綴是一個提示Spring使用基於角色的檢查的標記。
有了權限控制的規則了后,接下來我們需要定義一個AuthenticationManager用於認證。我們先來看如下定義:
<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(對應authentication-provider元素)來進行真正的認證,默認情況下authentication-provider對應一個DaoAuthenticationProvider,其需要UserDetailsService(對應user-service元素)來獲取用戶信息UserDetails(對應user元素)。這里我們只是簡單的使用user元素來定義用戶,而實際應用中這些信息通常都是需要從數據庫等地方獲取的,這個將放到后續再講。我們可以看到通過user元素我們可以指定user對應的用戶名、密碼和擁有的權限。user-service還支持通過properties文件來指定用戶信息,如:
<security:user-service properties="/WEB-INF/config/users.properties"/>
其中屬性文件應遵循如下格式:
username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
所以,對應上面的配置文件,我們的users.properties文件的內容應該如下所示:
#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的初始配置文件,也可以在對應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的配置文件是通過對應的ContextLoaderListener來加載和初始化的,上述代碼中的applicationContext.xml文件就是對應的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>
接下來可以啟動我們的應用,然后在瀏覽器中訪問我們的主頁。你會看到如下頁面。

因為我們的spring-security.xml文件中配置好了所有的請求都需要“ROLE_USER”權限,所以當我們在請求主頁的時候,Spring Security發現我們還沒有登錄,Spring會引導我們到登錄界面。使用正確的用戶名和密碼(如上面配置的user/user或admin/admin)登錄后,如果符合對應的權限我們就可以訪問主頁了,否則將出現403(禁止訪問)界面。
可能你會奇怪,我們沒有建立上面的登錄頁面,為什么Spring Security會跳到上面的登錄頁面呢?這是我們設置http的auto-config=”true”時Spring Security自動為我們生成的。
當指定http元素的auto-config=”true”時,就相當於如下內容的簡寫。
<security:http>
<security:form-login/>
<security:http-basic/>
<security:logout/>
</security:http>
這些元素負責建立表單登錄、基本的認證和登出處理。它們都可以通過指定對應的屬性來改變它們的行為。
