5. Java Configuration Java配置


在Spring 3.1中,對 Java Configuration (Java配置)的一般支持被添加到Spring框架中。自Spring Security 3.2以來,就有了Spring Security對Java配置的支持,用戶可以輕松配置Spring Security,而無需使用任何XML。

如果您熟悉第6章“安全命名空間配置”,那么您應該會發現它和安全Java配置支持之間有很多相似之處。

Spring Security提供了 lots of sample applications (許多示例應用程序),演示了Spring Security Java配置的使用。

5.1  Web Security Java Configuration(網絡安全Java配置)

第一步是創建我們的Spring安全Java配置。該配置創建了一個名為springSecurityFilterChain的Servlet過濾器,它負責應用程序中的所有安全性(保護應用程序URL、驗證提交的用戶名和密碼、重定向到登錄表單等)。您可以在下面找到Spring安全Java配置的最基本的例子:


 

1、這里真沒有配置多少內容,但它確實很有用。您可以找到以下功能的摘要:

2、在你的應用程序中對每個URL進行驗證

3、為你生成一個登陸表單

4、允許使用用戶名Usernameuser和密碼Passwordpassword使用驗證表單進行驗證。

5、允許用戶登出

6、CSRF attackCSPF攻擊防范

7、Session FixationSession保護

8、安全 Header 集成

 HTTP Strict Transport Security對安全要求嚴格的HTTP傳輸安全

 X-Content-Type-OptionsX-Content-Type-Options集成

        緩存控制(稍后可以允許你緩存靜態資源)

 X-XSS-ProtectionX-XSS-Protection集成

X-Frame-Options 集成防止點擊劫持Clickjacking

9、和以下 Servlet API 方法集成

HttpServletRequest#getRemoteUser()

 HttpServletRequest.html#getUserPrincipal()

 HttpServletRequest.html#isUserInRole(java.lang.String)

 HttpServletRequest.html#login(java.lang.String, java.lang.String)

 HttpServletRequest.html#logout()

5.1.1 AbstractSecurityWebApplicationInitializer(抽象安全網絡應用程序初始化器)

下一步是將springSecurityFilterChain注冊到war中。這可以在Servlet 3.0+環境中通過支持Spring的WebApplicationInitializer在Java配置中完成。不足為奇的是,Spring Security提供了一個基類AbstractSecurityWebApplicationInitializer(抽象安全性應用程序初始化器),它將確保為您注冊springSecurityFilterChain。我們使用AbstractSecurityWebApplicationInitializer(抽象安全性應用程序初始化器)的方式會有所不同,這取決於我們是否已經在使用Spring,或者Spring安全性是我們的應用程序中唯一的Spring組件。

第5.1.2節,“AbstractSecurityWebApplicationInitializer without Existing Spring”-如果您還沒有使用Spring,請使用這些說明。

第5.1.3節,“AbstractSecurityWebApplicationInitializer with Spring MVC”-如果您已經在使用Spring,請使用這些說明。

5.1.2 AbstractSecurityWebApplicationInitializer without Existing Spring(沒有現有Spring的抽象安全性應用程序初始化器)

如果您沒有使用Spring或Spring MVC,您將需要將網絡安全參數(WebSecurityConfig)傳入超類,以確保配置被采用。你可以在下面找到一個例子:


 

安全性應用程序初始化器(SecurityWebApplicationInitializer)將執行以下操作:

為應用程序中的每個網址自動注冊到springSecurityFilterChain過濾器。

添加一個加載網絡安全配置(WebSecurityConfig)的上下文加載器(ContextLoaderListener)。

5.1.3 AbstractSecurityWebApplicationInitializer with Spring MVC(有springMVC的抽象安全性應用程序初始化器 )

如果我們在應用程序的其他地方使用Spring,我們可能已經有了一個加載Spring配置的WebApplicationInitializer(web應用初始化器)。如果我們使用以前的配置,我們會得到一個錯誤。相反,我們應該在現有的應用上下文(ApplicationContext)中注冊Spring Security。例如,如果我們使用的是Spring MVC,我們的SecurityWebApplicationInitializer(安全web應用初始化器)看起來就像下面這樣:


 

這只會為應用程序中的每個網址注冊springSecurityFilterChain過濾器。之后,我們將確保WebSecurityConfig(web安全配置)加載到我們現有的應用程序初始化器中。例如,如果我們使用Spring MVC,它將被添加到getRootConfigClasses():


5.2 HttpSecurity(http安全)

到目前為止,我們的網絡安全配置只包含如何驗證用戶身份的信息。Spring Security如何知道我們想要要求所有用戶都經過身份驗證?Spring Security如何知道我們想要支持基於表單的身份驗證?原因是WebSecurityConfigurerAdapter(web安全配置適配器)在configure(HttpseSecurity http)方法中提供了一個默認配置,如下所示:


 

上面的默認配置:

確保我們應用中的所有請求都需要用戶被認證

允許用戶進行基於表單的認證

允許用戶使用HTTP基於驗證進行認證

你可以看到這個配置和下面的XML命名配置相似:


 

java配置使用and()方法相當於XML標簽的關閉。這允許我們繼續配置父對象。如果你閱讀代碼,它也是有意義的。我想配置授權請求,配置表單登錄和配置HTTP基本身份驗證。

然而,Java配置有不同的默認URL和參數。創建自定義登錄頁面時請記住這一點。結果是,我們的網址更加RESTful。此外,我們使用有助於防止信息泄露的Spring Security並不十分明顯。例如5.3所示:

5.3 Java Configuration and Form Login(java配置和表單登錄)

當提示您登錄時,您可能想知道登錄表單是從哪里來的,因為我們沒有提到任何HTML文件或JSP。由於Spring Security的默認配置沒有為登錄頁面明確設置URL,Spring Security會根據已啟用的功能自動生成一個,並使用處理提交的登錄的URL的標准值、用戶登錄后將被發送到的默認目標URL等等。

雖然自動生成的登錄頁面便於快速啟動和運行,但大多數應用程序都希望提供自己的登錄頁面。為此,我們可以更新我們的配置,如下所示:


 

1、指定登錄頁的路徑

2、我們必須允許所有用戶訪問我們的登錄頁(例如為驗證的用戶),這個formLogin().permitAll()方法允許基於表單登錄的所有的URL的所有用戶的訪問。

下面是我們當前配置的一個用JSPs實現的登錄頁面示例:

下面的登錄頁面代表我們當前的配置。如果某些默認值不能滿足我們的需求,我們可以輕松地更新我們的配置。


 

1、一個POST請求到/login用來驗證用戶

2、如果參數有error, 驗證嘗試失敗

3、如果請求蠶食logout存在則登出

4、登錄名參數必須被命名為username

5、密碼參數必須被命名為password

6、我們必須閱讀第18.4.3節“包含CSRF令牌”(Section 18.4.3, “Include the CSRF Token”)以了解更多信息,請閱讀第18章“跨站點請求偽造(CSRF)”(Chapter 18,Cross Site Request Forgery (CSRF))一節的參考資料

5.4 Authorize Requests(請求授權)

我們的例子中要求用戶進行身份驗證並且在我們應用程序的每個URL這樣做。我么你可以通過給http.authorizeRequests()添加多個子節點來指定多個定制需求到我們的URL。例如:


 

1、http.authorizeRequests()方法有多個子節點,每個macher按照他們的聲明順序執行。

2、我們指定任何用戶都可以通過訪問的多個URL模式。任何用戶都可以訪問URL以"/resources/", equals "/signup", 或者 "/about"開頭的URL。

3、以 "/admin/" 開頭的URL只能由擁有 "ROLE_ADMIN"角色的用戶訪問。請注意我們使用 hasRole 方法,沒有使用 "ROLE_" 前綴。

4、任何以"/db/" 開頭的URL需要用戶同時具有 "ROLE_ADMIN" 和 "ROLE_DBA"。和上面一樣我們的 hasRole 方法也沒有使用 "ROLE_" 前綴。

5、尚未匹配的任何URL要求用戶進行身份驗證。

5.5 Handling Logouts(登出處理)

當使用WebSecurityConfigurerAdapter, 注銷功能會自動應用。默認是訪問URL`/logout`將注銷登陸的用戶:

使HTTP Session 無效

清楚所有已經配置的 RememberMe 認證

清除SecurityContextHolder

重定向到 /login?logout


 

1、提供注銷支持,使用WebSecurityConfigurerAdapter會自動被應用。

2、設置觸發注銷操作的URL (默認是/logout). 如果CSRF內啟用(默認是啟用的)的話這個請求的方式被限定為POST。 請查閱相關信息JavaDoc相關信息.

3、注銷之后跳轉的URL。默認是/login?logout。具體查看JavaDoc文檔.

4、讓你設置定制的 LogoutSuccessHandler。如果指定了這個選項那么logoutSuccessUrl()的設置會被忽略。請查閱JavaDoc文檔.

5、指定是否在注銷時讓HttpSession無效。 默認設置為true。 在內部配置SecurityContextLogoutHandler,有關更多信息, 請查閱JavaDoc文檔.

6、添加一個LogoutHandler,默認情況下SecurityContextLogoutHandler會被添加為最后一個LogoutHandler。

7、允許指定在注銷成功時將移除的cookie。這是一個顯示的添加一個CookieClearingLogoutHandler的快捷方式。

注銷也可以通過XML命名空間進行配置,請參閱Spring Security XML命名空間相關文檔獲取更多細節logout element

5.5.1 LogoutHandler(登出處理器)

通常,LogoutHandle的r實現類能夠參與到注銷處理中。它們將被調用來執行必要的清理。因此,他們不應該拋出異常。提供了各種實現方式:

PersistentTokenBasedRememberMeServices(基於持久令牌的記憶服務)

TokenBasedRememberMeServices(基於令牌的記憶服務)

CookieClearingLogoutHandler(Cookie清除注銷處理程序)

CsrfLogoutHandler(Csrf注銷處理程序)

SecurityContextLogoutHandler(安全上下文注銷處理程序)

詳情請參見第17.4節“記住我的界面和實現”。(Section 17.4, “Remember-Me Interfaces and Implementations”

除了直接提供LogoutHandler實現,fluent應用編程接口還提供了快捷方式,這些快捷方式在封面下提供了各自的LogoutHandler實現。例如,deleteCookies()允許指定注銷成功時要刪除的一個或多個cookies的名稱。與添加CookieClearingLogoutHandler相比,這是一個快捷方式。

5.5.2 LogoutSuccessHandler(登出成功處理器)

LogoutSuccessHandler(登出成功處理器)被LogoutFilter(登出處理器)在成功注銷后調用,用來進行重定向或者轉發相應的目的地。注意這個接口與LogoutHandler(登出處理器)幾乎一樣,但是可以拋出異常。

下面是提供的一些實現:

SimpleUrlLogoutSuccessHandler(簡單URL登出成功處理器)

HttpStatusReturningLogoutSuccessHandler(http狀態返回登出成功處理器)

和前面提到的一樣,你不需要直接指定SimpleUrlLogoutSuccessHandler(簡單URL登出成功處理器)。而使用流式API接口通過設置logoutSuccessUrl(登出成功URL)快捷方式進行設置SimpleUrlLogoutSuccessHandler簡單URL登出成功處理器)。注銷成功 后將重定向到設置的URL地址。默認的地址是 /login?logout。

在REST API場景中HttpStatusReturningLogoutSuccessHandlerhttp狀態返回登出成功處理器)會進行一些有趣的改變。LogoutSuccessHandler(登出成功處理器)允許你設置一個返回給客戶端的HTTP狀態碼(默認返回200)來替換重定向到URL這個動作。

5.5.3 Further Logout-Related References(進一步登出相關參考)

Logout Handling(登出處理)

Testing Logout(登出測試)

HttpServletRequest.logout()(HTTPServletRequest登出)

Section 17.4, “Remember-Me Interfaces and Implementations”(Remember-Me接口和實現)

Logging Outin section CSRF Caveats (登出CSRF說明)

SectionSingle Logout(CAS protocol)(單點登出)

Documentation for thelogout elementin the Spring Security XML Namespace section(Spring安全XML命名空間部分中注銷元素的文檔)

5.6 Authentication(認證)

到目前為止,我們只看了最基本的身份驗證配置。讓我們看幾個稍微高級一點的配置身份驗證的選項。

5.6.1 In-Memory Authentication(內存中的身份驗證)

我們已經看到了一個單用戶配置到內存驗證的示例,下面是配置多個用戶的例子:

 


 

5.6.2 JDBC Authentication(jdbc認證)

你可以找一些更新來支持JDBC的驗證。下面的例子假設你已經在應用程序中定義好了DataSource, jdbc-javaconfig 示例提供了一個完整的基於JDBC的驗證。

 


 

5.6.3 LDAP Authentication(LDAP認證)

你可以找一些更新來支持LDAP的身份驗證, ldap-javaconfig 提供了一個完成的使用基於LDAP的身份驗證的示例。

 


 

上面的例子使用了下面的LDIF和一個嵌入的Apache DS LDAP實例。

dn: ou=groups,dc=springframework,dc=org

objectclass: top

objectclass: organizationalUnit

ou: groups

dn: ou=people,dc=springframework,dc=org

objectclass: top

objectclass: organizationalUnit

ou: people

dn: uid=admin,ou=people,dc=springframework,dc=org

objectclass: top

objectclass: person

objectclass: organizationalPerson

objectclass: inetOrgPerson

cn: Rod Johnson

sn: Johnson

uid: admin

userPassword: password

dn: uid=user,ou=people,dc=springframework,dc=org

objectclass: top

objectclass: person

objectclass: organizationalPerson

objectclass: inetOrgPerson

cn: Dianne Emu

sn: Emu

uid: user

userPassword: password

dn: cn=user,ou=groups,dc=springframework,dc=org

objectclass: top

objectclass: groupOfNames

cn: user

uniqueMember: uid=admin,ou=people,dc=springframework,dc=org

uniqueMember: uid=user,ou=people,dc=springframework,dc=org

dn: cn=admin,ou=groups,dc=springframework,dc=org

objectclass: top

objectclass: groupOfNames

cn: admin

uniqueMember: uid=admin,ou=people,dc=springframework,dc=org

5.6.4 AuthenticationProvider(認證提供商)

您可以通過一個自定義的AuthenticationProvider為bean定義自定義身份驗證。 例如, 下面這個例子假設自定義身份驗證SpringAuthenticationProvider實現了AuthenticationProvider:

僅當尚未填充AuthenticationManagerBuilder時,才使用此選項。

 


 

5.6.5 UserDetailsService(用戶詳細信息服務)

你可以通過一個自定義的UserDetailsService(用戶詳細信息服務)為bean定義自定義身份驗證。 例如,下面這個例子假設自定義身份驗證SpringDataUserDetailsService實現了UserDetailsService:

僅當尚未填充AuthenticationManagerBuilder(身份驗證管理器生成器)並且未定義AuthenticationProviderBean(身份驗證提供商)時,才使用此選項。

 


 

你也可以通過讓passwordencoder為bean自定義密碼如何編碼。 例如,如果你使用BCrypt,你可以添加一個bean定義如下圖所示:

 


5.6.6 LDAP Authentication(LDAP身份認證)

5.7 Multiple HttpSecurity(多個HttpSecurity)

我們可以配置多個http安全實例,就像我們可以有多個< http >塊一樣。關鍵是多次擴展WebSecurityConfigurerAdapter。例如,下面是一個為以/api/開頭的網址進行不同配置的示例。

 


 

配置正常的驗證。

1、創建一個WebSecurityConfigurerAdapter,包含一個@Order注解,用來指定個哪一個WebSecurityConfigurerAdapter更優先。

2、http.antMatcher指出,這個HttpSecurity只應用到以/api/開頭的URL上。

3、創建另外一個WebSecurityConfigurerAdapter實例。用於不以/api/開頭的URL,這個配置的順序在ApiWebSecurityConfigurationAdapter之后,因為他沒有指定@Order值為1(沒有指定@Order默認會被放到最后).

5.8 Method Security(方法安全性)

從版本2.0開始,Spring Security已經大大改進了對為服務層方法增加安全性的支持。它支持JSR-250注釋安全性以及框架的原始@Secured注釋。從3.0開始,您還可以使用新的基於表達式(expression-based annotations.)的注釋。您可以對單個bean應用安全性,使用intercept-methods元素來修飾bean聲明,或者使用AspectJ風格的切入點來保護整個服務層中的多個bean。

5.8.1 EnableGlobalMethodSecurity(啟用全局方法安全性)

我們可以在任何@Configuration實例上使用@EnableGlobalMethodSecurity注釋來啟用基於注釋的安全性。例如,下面將啟用Spring Security的@Secured注釋。

 


 

向方法(在類或接口上)添加注釋會相應地限制對該方法的訪問。Spring Security的原生注釋支持為該方法定義了一組屬性。這些將被傳遞給AccessDecisionManager(訪問決策管理器),以便它做出實際的決策:

 


 

使用如下代碼啟用JSR-250注解的支持

 


 

這些都是基於標准的,允許應用簡單的基於角色的約束,但不具備Spring Security的原生注釋。要使用新的基於表達式的語法,您應該使用

 


 

等效的Java代碼是

 


 

5.8.2 GlobalMethodSecurityConfiguration(全局方法安全性配置)

有時您可能需要執行比@EnableGlobalMethodSecurity注釋允許的操作更復雜的操作。對於這些實例,您可以擴展GlobalMethodsecurityConfiguration(全局方法安全性配置),確保您的子類中存在@EnableGlobalMethodSecurity注釋。例如,如果您想提供一個自定義的MethodSecurityExpressionHandler(方法安全表達式處理程序),您可以使用以下配置:

 


 

關於可以被重寫的方法的更多信息,請參考GlobalMethodSecurityConfiguration(全局方法安全性配置)的java文檔。

5.9 Post Processing Configured Objects(后置處理配置的對象)

Spring Security的Java配置沒有公開它配置的每個對象的每個屬性。這簡化了大多數用戶的配置。畢竟,如果每個屬性都公開了,用戶可以使用標准的bean配置。

雖然有充分的理由不直接公開每個屬性,但是用戶可能仍然需要更高級的配置選項。為了解決這個問題,Spring Security引入了ObjectPostProcessor(后置對象處理器)的概念,它可以用來修改或替換許多由Java配置創建的對象實例。例如,如果您想在FilterSecurityInterceptor(安全過濾攔截器)上配置FilterSecurityPublishauthorizationSuccess(安全過濾發布授權成功)屬性,可以使用以下方法:

 


 

5.10 Custom DSLs(自定義DSLs)

您可以在Spring Security中提供自己的定制DSL。例如,你可能有這樣的東西:

 


 

這實際上是像HttpSecurity.authorizeRequests()這樣的方法是來實現的。

自定義DSL可以這樣使用:

 


 

代碼按以下順序調用:

1、調用“配置”的配置方法中的代碼

2、調用了“MyCustomDsl的初始化方法”中的代碼

3、調用了“MyCustomDsl的配置方法”中的代碼

如果需要,您可以使用SpringFactories讓WebSecurityConfiguerAdapter默認添加MyCustomDsl。例如,您可以在類路徑上創建一個名為META-INF/spring.factories的資源,其內容如下:

org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyCustomDsl

希望禁用默認值的用戶可以明確地這樣做。

 


 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM