SPRING SECURITY JAVA配置:Web Security

前一篇,我已經介紹了Spring Security Java配置,也歸納的介紹了一下這個項目方方面面。在這篇文章中,咱們來看一看一個簡單的基於web security配置的例子。以後咱們再來做更多的我的定製。php

Hello Web Security

在這個部分,咱們對一個基於web的security做一些基本的配置。能夠分紅四個部分:html

WebSecurityConfigurerAdapter

@EnableWebSecurity註解以及WebSecurityConfigurerAdapter一塊兒配合提供基於web的security。繼承了WebSecurityConfigurerAdapter以後,再加上幾行代碼,咱們就能實現如下的功能:java

  • 要求用戶在進入你的應用的任何URL以前都進行驗證
  • 建立一個用戶名是「user」,密碼是「password」,角色是「ROLE_USER」的用戶
  • 啓用HTTP Basic和基於表單的驗證
  • Spring Security將會自動生成一個登錄頁面和登出成功頁面
1
2
3
4
5
6
7
8
9
10
@Configuration
@EnableWebSecurity
public class HelloWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
 
@Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
.withUser( "user" ).password( "password" ).roles( "USER" );
}
}

做爲參考,咱們在這裏也給出類似的XML配置,不過有幾個特殊配置:git

  • Spring Security會生成一個登錄頁面,驗證失敗頁面和登出成功頁面
  • login-processing-url僅僅處理HTTP POST
  • login-page僅僅經過HTTP GET進入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
< http use-expressions = "true" >
   < intercept-url pattern = "/**" access = "authenticated" />
   < logout
     logout-success-url = "/login?logout"
     logout-url = "/logout"
   />
   < form-login
     authentication-failure-url = "/login?error"
     login-page = "/login"
     login-processing-url = "/login"
     password-parameter = "password"
     username-parameter = "username"
   />
</ http >
< authentication-manager >
   < authentication-provider >
     < user-service >
       < user name = "user"
           password = "password"
           authorities = "ROLE_USER" />
     </ user-service >
   </ authentication-provider >
</ authentication-manager >

AbstractAnnotationConfigDispatcherServletInitializergithub

下一步就是保證ApplicationContext包含咱們剛剛定義的HelloWebSecurityConfiguration。有幾種方法均可行,咱們這裏使用Spring的AbstractAnnotationConfigDispatcherServletInitializerweb

1
2
3
4
5
6
7
8
9
public class SpringWebMvcInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
 
@Override
protected Class[] getRootConfigClasses() {
return new Class[] { HelloWebSecurityConfiguration. class };
}
...
}

Spring Security一般在web.xml中包含下面幾行代碼進行初始化:spring

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Creates the Spring Container shared by all Servlets and Filters -->
< listener >
   < listener-class >
     org.springframework.web.context.ContextLoaderListener
   </ listener-class >
</ listener >
 
<!-- Load all Spring XML configuration including our security.xml file -->
< context-param >
   < param-name >contextConfigLocation</ param-name >
   < param-value >/WEB-INF/spring/*.xml</ param-value >
</ context-param >

AbstractSecurity WebApplicationInitializer

最後一步,咱們須要對springSecurityFilterChain定義映射路徑。咱們很容易經過繼承AbstractSecurityWebApplicationInitializer實現,並能夠有選擇的經過覆蓋方法來定製映射。express

下面是最基本的配置,它能夠接受默認的映射路徑,springSecurityFilterChain具備如下的特性:api

  • springSecurityFilterChain映射到了」/*」
  • springSecurityFilterChain使用ERROR和REQUEST分派類型(dispatch type)
  • springSecurityFilterChain插入到其它已經配置的servlet過濾器映射(servlet Filter mapping)以前
1
2
3
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}

上面的代碼等同於將這幾行代碼放在web.xml中:安全

1
2
3
4
5
6
7
8
9
10
11
12
13
< 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 >
   < dispatcher >ERROR</ dispatcher >
   < dispatcher >REQUEST</ dispatcher >
</ filter-mapping >

WebApplicationInitializer的次序
在AbstractSecurityWebApplicationInitializer啓動以後再加入的servlet過濾器映射,它們有可能會加在springSecurityFilterChain以前。除非這個應用不須要安全驗證,不然springSecurityFilterChain須要放在其它全部的過濾器映射以前。@Order能夠保證任何WebApplicationInitializer都使用特定的順序加載。

CustomWebSecurityConfigurerAdapter

這個HelloWebSecurityConfiguration範例,爲咱們很好的展現了Spring Security Java配置是如何工做的。讓咱們來看看更多定製的配置吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@EnableWebSecurity
@Configuration
public class CustomWebSecurityConfigurerAdapter extends
WebSecurityConfigurerAdapter {
@Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser( "user" ) // #1
.password( "password" )
.roles( "USER" )
.and()
.withUser( "admin" ) // #2
.password( "password" )
.roles( "ADMIN" , "USER" );
}
 
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers( "/resources/**" ); // #3
}
 
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeUrls()
.antMatchers( "/signup" , "/about" ).permitAll() // #4
.antMatchers( "/admin/**" ).hasRole( "ADMIN" ) // #6
.anyRequest().authenticated() // #7
.and()
.formLogin() // #8
.loginUrl( "/login" ) // #9
.permitAll(); // #5
}
}

咱們也須要更新AbstractAnnotationConfigDispatcherServletInitializer,這樣CustomWebSecurityConfigurerAdapter能夠實現如下功能:

  • #1 能夠在內存中的驗證(memory authentication)叫做」user」的用戶
  • #2 能夠在內存中的驗證(memory authentication)叫做」admin」的管理員用戶
  • #3 忽略任何以」/resources/」開頭的請求,這和在XML配置http@security=none的效果同樣
  • #4 任何人(包括沒有通過驗證的)均可以訪問」/signup」和」/about」
  • #5 任何人(包括沒有通過驗證的)均可以訪問」/login」和」/login?error」。permitAll()是指用戶能夠訪問formLogin()相關的任何URL。
  • #6 「/admin/」開頭的URL必需要是管理員用戶,譬如」admin」用戶
  • #7 全部其餘的URL都須要用戶進行驗證
  • #8 使用Java配置默認值設置了基於表單的驗證。使用POST提交到」/login」時,須要用」username」和」password」進行驗證。
  • #9 註明了登錄頁面,意味着用GET訪問」/login」時,顯示登錄頁面

下面的XML配置和上面的Java配置相似:

Java配置和XML命名空間的相同之處

在看過了更復雜的例子以後,你可能已經找到了一些XML命名空間和Java配置的類似之處。我在這裏說明幾條有用的信息:

  • HttpSecurity和http命名空間相似。它能夠對於某一部分請求進行特別配置。要看個完整的配置實例,詳見SampleMultiHttpSecurityConfig
  • WebSecurity和Security的命名空間的元素很相似,後者是針對web的,不須要父節點(security=none, debug等等)。能夠對整個web security進行配置。
  • WebSecurityConfigurerAdapter方便咱們定製WebSecurity和HttpSecurity。咱們能夠對WebSecurityConfigurerAdapter進行屢次繼承,以實現不一樣的http行爲。詳細的實例參見SampleMultiHttpSecurityConfig
  • 咱們以上的Java配置代碼做了代碼格式化,因此易於閱讀。「and()」相似於XML中結束一個元素的結束符。

Java配置和XML命名空間的不一樣之處

你已經意識到了XML和Java配置的不一樣之處

  • 當你在」#1″和「#2」中建立用戶的時候,咱們並無設置爲」ROLE_前綴,而咱們在XML設置成了「ROLE_USER」。由於這是個管理,」roles()」方法會自動添加」ROLE_「。若是你不想要」ROLE_「,你可使用」authoritites()」方法。
  • Java配置有一些不一樣的默認URL和參數。當要建立自定義的登錄頁面的時候要將這一條牢記在心。默認的URL使咱們的URL更加RESTful。另外,使用Spring Security能夠幫我避免信息泄露)。例如:
    • GET訪問/login登錄頁面,而不是訪問/spring_security_login
    • POST訪問/login,而不是/j_spring_security_check
    • 用戶名默認爲parameter,而不是j_username
    • 密碼默認是password,而不是j_password
  • Java配置能夠更容易將多個請求映射到一樣的角色上。#4就將兩個URL做了映射,以便全部人均可以訪問
  • Java移除了多餘的代碼。例如,在XML中咱們不得不在form-loginintercept-url中重複兩次」/login」,而在Java配置中,咱們靠#5就輕易作到了讓用戶都能訪問到和formLogin()相關的URL。
  • #6映射HTTP請求的時候,咱們使用了「hasRole()」方法,咱們也沒有添加」ROLE_」前綴,而在XML中咱們則添加了。這也是咱們應該知道的慣例:」hasRole()」會自動添加」ROLE_」前綴。若是你不想要「ROLE_」前綴,你可使用」access()」方法。

更多的示例

咱們還提供了更多的示例,你應該想躍躍欲試了吧:

從XML命名空間到Java配置

若是你以爲從XML轉變成Java配置有必定困難,你能夠先看看這些測試。這些測試中,XML元素的名稱以」Namespace」開頭,中間是XML元素的名稱,而後以」Tests」結尾。例如,你想學習如何將http元素轉換成Java配置,你能夠看看NamespaceHttpTests;你若是想學習如何將remember-me命名空間轉換成Java配置,參見NamespaceRememberMeTests

歡迎反饋

若是你發現了bug,或者以爲有什麼地方值得改進,請你不要猶豫,給咱們留言!咱們但願聽到你的想法,以便在大部分人得到代碼以前,咱們便確保代碼的正確性。很早的嘗試新功能是一種簡單有效的回饋社區的方法,這樣作的好處就是能幫助你得到你但願得到的功能。

請到「Java Config」目錄下的Spring Security JIRA記錄下任何問題。記錄了一個JIRA以後,咱們但願(固然並非必須的)你在pull request中提交你的代碼。你能夠在貢獻者指引中閱讀更詳細的步驟。若是你有任何不清楚的,請使用Spring Security論壇或者Stack Overflow,並使用」spring-security」標籤(我會一直查看這個標籤)。若是你針對這個博客有任何意見,也請留言。使用合適的工具對每一個人來講都會帶來便利。

結論

你可能已經對基於web的security的Java配置已經有了必定的認識了。下一篇中,咱們將會帶你來看下如何用Java配置來配置基於method的security。

原文連接: Springsource 翻譯: ImportNew.com 唐小娟
譯文連接: http://www.importnew.com/5641.html
轉載請保留原文出處、譯者和譯文連接。]

相關文章
相關標籤/搜索