Spring Security 參考手冊(二)

受權

在Spring Security的高級受權功能是其受歡迎的最有說服力的緣由之一,不管您如何選擇如何進行身份驗證-是否使用提供的機制和提供程序的Spring Security,或整合與一個容器或其餘non-Spring Security 認證機構-你會發現受權服務能夠在您的應用程序中使用一個一致的和簡單的方式.javascript

在這一部分咱們將探討不一樣的` abstractsecurityinterceptor `實現,在第一部分介紹.而後,咱們將繼續探索如何經過使用域訪問控制列表微調受權.html

受權體系結構

受權

正如咱們在<<技術授予權,技術綜述 >>所看到,全部的Authentication實現存儲的列表GrantedAuthority對象.這些表明已被授予主要的的當局. GrantedAuthority對象是由` authenticationManager 插入到`Authentication 對象,而後讀取 AccessDecisionManager作出判斷.java

GrantedAuthority是一個只有一個方法的接口node

String getAuthority();

這個方法容許AccessDecisionManager 來判斷獲得一個精確的String表示的` GrantedAuthority .經過返回一個表示做爲一個`String,一個` GrantedAuthority 能夠很容易的經過`AccessDecisionManager 來read,若是一個` GrantedAuthority 不能精確地表示爲一個`String,` GrantedAuthority 將會被認爲是"complex"和`getAuthority() 必須返回爲null.mysql

"complex" GrantedAuthority的一個將一個應用於不一樣客戶賬戶號碼的操做和權限閾值的列表的實現例子.表明這個複雜的` GrantedAuthority 做爲`String將是至關困難的,做爲一個結果,` getauthority() 方法應該返回`null.這將對任何` accessDecisionManager 代表它須要明確的支持 GrantedAuthority `實施以瞭解其內容.git

Spring Security包括一個具體的` GrantedAuthority 實施, grantedauthorityimpl .這容許用戶指定的任何String轉換成一種` GrantedAuthority .全部的 AuthenticationProvider 的包括與安全架構使用 grantedauthorityimpl`填充Authentication對象.github

Pre-Invocation處理

正如咱們在<<安全對象、技術綜述>>章節中也看到過的,Spring Security,提供攔截控制訪問安全對象如方法調用或Web請求。是否容許進行調用前調用的決定是由`AccessDecisionManager `做出判斷.web

訪問決策管理器

` accessDecisionManager  abstractsecurityinterceptor 和負責制定最終的訪問控制決策.`AccessDecisionManager接口包含三種方法:ajax

void decide(Authentication authentication, Object secureObject,
	Collection<ConfigAttribute> attrs) throws AccessDeniedException;

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);

AccessDecisionManagerdecide方法傳遞了它所須要的全部相關信息,以做出受權決策.尤爲,經過安全的「對象」,使這些參數包含在實際的安全對象調用中進行檢查.例如,讓咱們假設安全對象是一個MethodInvocation `資料,這將是很容易實現`MethodInvocation對於任何Customer論點.而後執行某種安全邏輯判斷、來確保AccessDecisionManager `主容許對客戶操做.若是訪問被拒絕並拋出`AccessDeniedException 咱們的預期就實現了.正則表達式

若是` accessDecisionManager 能夠處理經過 configattribute ,`supports(ConfigAttribute)方法由AbstractSecurityInterceptor 在決定啓動時候命名. supports(Class) 方法被安全攔截器實現,確保配置` accessDecisionManager `支持類型的安全對象的被攔截.

Voting-Based訪問決策管理器實現

同時,用戶能夠實現本身的` AccessDecisionManager`判斷、控制受權的全部方面,Spring Security包括幾個基於投票的` accessDecisionManager `實現. Voting Decision Manager說明相關類.

access decision voting.png
Figure 2. Voting Decision Manager

使用這種方法,一系列的` accessdecisionvoter 實現調查受權決策. accessDecisionManager 而後決定是否拋出accessdeniedexception `基於其選票的評估。

AccessDecisionVoter接口包含三種方法:

int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attrs);

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);

具體返回一個int,可能反映在` accessdecisionvoter 的靜態字段 access_abstain  access_denied  access_granted .若是對受權決策沒有意見一個投票的實施將返回 access_abstain . 若是真的有一個觀點,它必須返回 access_denied access_granted `.

這裏三個具體的AccessDecisionManager提供了符合投票的 Spring Security,` consensusbased 實施將授予或拒絕基於非共識的棄權票的訪問.提供的屬性來控制在一個平等的投票活動的行爲,或者若是全部的選票都棄權. affirmativebased 實施將會受權訪問若是你個或者更多的`ACCESS_GRANTED 投票被收到(即便投票被忽略,也至少有一個投票).像「ConsensusBased」實現,有一個參數,控制行爲若是全部選民棄權.UnanimousBased的提供者預計一致ACCESS_GRANTED的選票以授予訪問權限,忽略了自制。它會拒絕訪問若是有任何「ACCESS_DENIED」投票.像其餘實現,有一個參數,控制行爲若是全部選民棄權.

能夠實現自定義` accessDecisionManager 計算選票不一樣。例如,從一個特定的 accessdecisionvoter `可能會獲得額外的加權投票,而否定從一個特定的選民投票可能有否決權的影響.

角色選民

最經常使用的由Spring Security提供的AccessDecisionVoter 是簡單的RoleVoter,若是用戶已被分配該角色,將配置屬性視爲簡單的角色名稱和投票授予訪問權限.

若是ConfigAttribute 帶着前綴ROLE_開始將會進行投票,它將投票授予訪問權限,若是有` GrantedAuthority 它返回一個`String表示(經過` getauthority() 方法)剛好等於一個或多個從前綴 role_  configattributes .若是沒有從 role_ 精確匹配任何 configattribute  rolevoter 會投票拒絕訪問。若是 role_ 沒有開始 configattribute `,選民將投棄權票。

通過身份驗證的選民

另外一個選民,咱們從 AuthenticatedVoter看到,能夠用來區分匿名,fully-authenticated,記得我經過身份驗證的用戶,許多網站容許某些有限的訪問在記得我認證,可是須要用戶確認他們的身份登陸的徹底訪問.當咱們使用屬性IS_AUTHENTICATED_ANONYMOUSLY授予匿名訪問,這個屬性是由「AuthenticatedVoter」進行處理。有關更多信息,請參見這個類的Javadoc.

定製的選民

顯然,您還能夠實現自定義「AccessDecisionVoter」,你能夠把任何你想要訪問控制邏輯.這多是特定於應用程序(業務邏輯相關)或可能實現一些安全管理邏輯,例如你會發現 blog article 在Spring web網站描述如何使用實時選民拒絕訪問用戶的帳戶被暫停.

調用處理

而「AccessDecisionManager」是由「AbstractSecurityInterceptor」在繼續以前調用安全對象調用.某些應用程序須要一種方法修改對象的實際安全返回的對象調用.同時您能夠很容易地實現本身的AOP實現這一擔心, Spring Security提供了一個方便的鉤,幾個集成ACL的功能的具體實現.

After Invocation Implementation說明了Spring Security的AfterInvocationManager 以及這個具體實現.

after invocation.png
Figure 3. After Invocation Implementation

像Spring Security的其餘部分,AfterInvocationManager 有一個具體的實現,AfterInvocationProviderManager調查AfterInvocationProvider的表,每個AfterInvocationProvider容許修改返回對象或拋出AccessDeniedException.的確多個提供者能夠修改對象,如以前的供應商的結果傳遞給下一個列表中.

請注意,若是您正在使用AfterInvocationManager,你仍然須要配置屬性,使MethodSecurityInterceptorAccessDecisionManager容許一個操做.若是您使用的是典型的Spring Security包括「AccessDecisionManager」實現,沒有配置屬性定義爲一個特定的安全方法調用將致使每一個「AccessDecisionVoter」投棄權票,相反,若是AccessDecisionManager 性能 「allow IfAllAbstainDecisions」是false就會拋出一個 AccessDeniedException,你能夠經過設置「allowIfAllAbstainDecisions」避免這種潛在的問題改變爲true(雖然這是通常不推薦),或者(ii)只是確保至少有一個配置屬性,一個「AccessDecisionVoter」將投票受權訪問,後者(推薦)的方法一般是經過「ROLE_USER」或「ROLE_AUTHENTICATED」配置屬性.

層次的角色

它是一個共同的要求,一個特定的應用程序中的角色應該自動"include"其餘角色,例如,在一個應用程序中有一個"admin" 和"user"的角色的概念,你可能但願一個管理員可以盡一切正常的用戶能夠。要作到這一點,你能夠確保全部的管理用戶也被分配到"user"的角色.另外,您能夠修改每個訪問約束,這須要"user"的角色,還包括"admin"的做用.這可能會變得至關複雜,若是你有不少不一樣的角色在你的應用程序.

使用角色層次結構容許您配置哪些角色(或主管)應包括其餘角色(或主管部門).一個額外的of Spring Security’s RoleVoter的版本,RoleHierarchyVoter配置了一個` rolehierarchy `,從它得到全部的"reachable authorities",用戶被分配。一個典型的配置可能看起來像這樣:

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
	<constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
		class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
	<property name="hierarchy">
		<value>
			ROLE_ADMIN > ROLE_STAFF
			ROLE_STAFF > ROLE_USER
			ROLE_USER > ROLE_GUEST
		</value>
	</property>
</bean>

在這裏,咱們有四個角色在一個層次結構 ROLE_ADMIN ⇒ ROLE_STAFF ⇒ ROLE_USER ⇒ ROLE_GUEST.經過身份驗證的用戶ROLE_ADMIN, 要表現得好像他們全部的四種角色在安全約束的評價與判斷,要表現得好像他們全部的四種角色在安全約束的評價與判斷,AccessDecisionManager 配置上述RoleHierarchyVoter.>符號能夠被認爲是意義的"includes".

角色層次結構提供了一個方便的方法簡化了您的應用程序的訪問控制配置數據和/或減小您須要分配給用戶的權限數.對於更復雜的要求,您可能但願定義您的應用程序所需的特定訪問權限和被分配給用戶的角色之間的邏輯映射,在加載用戶信息時將二者翻譯成二者之間的關係.

安全對象的實現

AOP聯盟(方法調用)安全攔截器

Spring Security 2.0以前,確保`MethodInvocation`資料須要至關多的配置.如今方法安全的推薦方法是使用< <ns-method-security,namespace configuration>>.這種方法的安全基礎設施beans是爲您自動配置的,因此您不須要知道實現類的狀況。咱們將提供一個在這裏涉及的類的快速概述。

方法在執行安全使用` methodsecurityinterceptor ,這是一個固定的`MethodInvocation .根據配置的方法,一個攔截多是特定的一個單一的bean或多個beans之間的共享.攔截器使用` methodsecuritymetadatasource 實例獲取配置屬性,適用於一個特定的方法調用.`MapBasedMethodSecurityMetadataSource用於存儲配置屬性的鍵控的方法名稱(能夠使用通配符),將在內部使用時,這些屬性定義在應用程序的上下文中使用的<intercept-methods>攔截或<protect-point>元素。

固然你能夠使用一個Spring AOP的代理機制配置一個` methodsecurityiterceptor `直接應用程序上下文中:

<bean id="bankManagerSecurity" class=
	"org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="afterInvocationManager" ref="afterInvocationManager"/>
<property name="securityMetadataSource">
	<sec:method-security-metadata-source>
	<sec:protect method="com.mycompany.BankManager.delete*" access="ROLE_SUPERVISOR"/>
	<sec:protect method="com.mycompany.BankManager.getBalance" access="ROLE_TELLER,ROLE_SUPERVISOR"/>
	</sec:method-security-metadata-source>
</property>
</bean>

AspectJ(鏈接點)安全攔截器

AspectJ的安全攔截器是AOP聯盟安全攔截器在上一節討論很是類似。事實上,咱們將只討論在這一部分的差別.

AspectJ攔截器被命名爲 AspectJSecurityInterceptor.不像AOP聯盟安全攔截器,它依賴於Spring應用程序上下文編織的安全攔截器經過代理,AspectJSecurityInterceptor是基於AspectJ編譯器.不會罕見的在同一個程序中使用的兩種安全攔截器,與AspectJSecurityInterceptor用於域對象實例安全,AOP聯盟` methodsecurityinterceptor `用於服務層安全.

讓咱們首先考慮的是如何AspectJSecurityInterceptor配置在Spring應用程序上下文:

<bean id="bankManagerSecurity" class=
	"org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="afterInvocationManager" ref="afterInvocationManager"/>
<property name="securityMetadataSource">
	<sec:method-security-metadata-source>
	<sec:protect method="com.mycompany.BankManager.delete*" access="ROLE_SUPERVISOR"/>
	<sec:protect method="com.mycompany.BankManager.getBalance" access="ROLE_TELLER,ROLE_SUPERVISOR"/>
	</sec:method-security-metadata-source>
</property>
</bean>

正如你所看到的,除了類名稱,AspectJSecurityInterceptor是徹底同樣的AOP聯盟安全攔截器.事實上,兩個攔截器能夠共享相同的` securitymetadatasource ,做爲 securitymetadatasource 做品 `java.lang.reflect.Method而不是AOP庫類。固然,你訪問的決定得到有關特定AOP庫調用(即` MethodInvocation 或`JoinPoint),這樣能夠使訪問的決定時,考慮的範圍以外的標準(如方法的參數).

下次你須要定義一個AspectJ aspect.例如:

package org.springframework.security.samples.aspectj;

import org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor;
import org.springframework.security.access.intercept.aspectj.AspectJCallback;
import org.springframework.beans.factory.InitializingBean;

public aspect DomainObjectInstanceSecurityAspect implements InitializingBean {

	private AspectJSecurityInterceptor securityInterceptor;

	pointcut domainObjectInstanceExecution(): target(PersistableEntity)
		&& execution(public * *(..)) && !within(DomainObjectInstanceSecurityAspect);

	Object around(): domainObjectInstanceExecution() {
		if (this.securityInterceptor == null) {
			return proceed();
		}

		AspectJCallback callback = new AspectJCallback() {
			public Object proceedWithObject() {
				return proceed();
			}
		};

		return this.securityInterceptor.invoke(thisJoinPoint, callback);
	}

	public AspectJSecurityInterceptor getSecurityInterceptor() {
		return securityInterceptor;
	}

	public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) {
		this.securityInterceptor = securityInterceptor;
	}

	public void afterPropertiesSet() throws Exception {
		if (this.securityInterceptor == null)
			throw new IllegalArgumentException("securityInterceptor required");
		}
	}
}

在上面的例子中,安全攔截器將被應用到每個實例` persistableentity ,這是一個抽象類沒有顯示(你能夠使用任何其餘類或`pointcut表達你喜歡).對於那些好奇的人,` aspectjcallback 是由於 proceed();聲明具備特殊的意義只有在 around() 體。當它想要的目標繼續,`AspectJSecurityInterceptor 調用這個匿名` aspectjcallback `類.

你須要配置Spring 負載方面和鏈接AspectJSecurityInterceptor。一個實現這一的bean聲明以下所示:

<bean id="domainObjectInstanceSecurityAspect"
	class="security.samples.aspectj.DomainObjectInstanceSecurityAspect"
	factory-method="aspectOf">
<property name="securityInterceptor" ref="bankManagerSecurity"/>
</bean>

是這麼回事!如今你能夠從你的應用程序中的任何地方建立你的豆子,使用任何你認爲合適的方式(eg new Person();)他們會擁有安全攔截器的應用

表達式的訪問控制

Spring Security 3.0介紹了使用的能力,做爲一個受權機制,除了簡單的使用配置屬性和訪問決策的選民,之前見過的使用彈簧的表達。基於表達式的訪問控制是創建在相同的架構,但容許複雜的布爾邏輯被封裝在一個單一的表達.

概述

Spring Security 使用Spring EL來支持,你應該看看如何,若是你有興趣在更深刻了解主題。表達式是用"root object" 評估的,做爲評價上下文的一部分。Spring Security使用特定的類用於Web和方法安全做爲根對象,以提供內置表達式和訪問當前主體的值等.

常見的內置的表達式

表達根對象的基類是` securityexpressionroot `.這提供了一些常見的表達式,可應用在網絡和方法安全性.

Table 3. Common built-in expressions
表達 描述

hasRole([role])

若是當前主體具備指定的角色,則返回true.默認狀況下,若是提供的角色不從'ROLE_'這裏提供,這將增長。這能夠經過修改` defaultroleprefix  defaultwebsecurityexpressionhandler `配置.

hasAnyRole([role1,role2])

若是當前的主體有任何提供的角色(給定的做爲一個逗號分隔的字符串列表)的話,返回true,默認狀況下,若是提供的角色不從 'ROLE_',這將增長。這能夠經過修改` defaultroleprefix defaultwebsecurityexpressionhandler `定製.

hasAuthority([authority])

若是當前的主體具備指定的權限,則返回 true.

hasAnyAuthority([authority1,authority2])

若是當前的主體有任何提供的角色(給定的做爲一個逗號分隔的字符串列表)的話,返回true.

principal

容許直接訪問表示當前用戶的主對象

authentication

容許直接訪問從SecurityContext得出當前的Authentication對象

permitAll

老是評估爲true

denyAll

老是評估爲false

isAnonymous()

若是當前的主體是一個匿名用戶,則返回true.

isRememberMe()

若是當前的主體是一個匿名用戶,則返回true

isAuthenticated()

若是用戶不是匿名的,則返回 true

isFullyAuthenticated()

若是用戶不是一個匿名的或是一個記住個人用戶返回true

hasPermission(Object target, Object permission)

若是用戶已訪問給定權限的提供的目標,則返回true,例如hasPermission(domainObject, 'read')

hasPermission(Object targetId, String targetType, Object permission)

若是用戶已訪問給定權限的提供的目標,則返回true,例如hasPermission(1, 'com.example.domain.Message', 'read')

Web Security Expressions

使用表達式來保護我的網址,首先須要設置「use-expressions」屬性的< http >爲true.Spring Security預期的「訪問」屬性的< intercept-url >元素包含Spring EL表達式。一個布爾表達式應該評估,定義是否應該容許訪問. 例如:

<http>
	<intercept-url pattern="/admin*"
		access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
	...
</http>

這裏咱們定義了應用程序的「admin」區域(定義的URL模式)只能提供給用戶授予機關「admin」,其IP地址匹配本地子網.在前一節中咱們已經看到內置hasRole表達式。表達「hasIpAddress」是另外一個內置的表達式是特定於網絡安全.這由WebSecurityExpressionRoot下定義,一個實例時用做表達式根對象評估web訪問表達式。這個對象也直接暴露的HttpServletRequest對象的名字「請求」,這樣你就能夠直接調用請求在一個表達式。若是正在使用表情,「WebExpressionVoter」將被添加到「AccessDecisionManager」所使用的名稱空間. 若是你不使用名稱空間和想使用表情,你必須添加一個配置.

在網絡安全bean表達式

若是你想擴展表達式可用,您能夠很容易地操做任何你暴露的Spring Bean。例如,assumming你有一個Bean的名稱「webSecurity」包含如下方法

public class WebSecurity {
		public boolean check(Authentication authentication, HttpServletRequest request) {
				...
		}
}

你能夠參考使用方法:

<http>
	<intercept-url pattern="/user/**"
		access="@webSecurity.check(authentication,request)"/>
	...
</http>

或在Java配置

http
		.authorizeRequests()
				.antMatchers("/user/**").access("@webSecurity.check(authentication,request)")
				...

Path Variables in Web Security Expressions

有時在一個URL它很好可以參考路徑變量. 例如,考慮一個RESTful應用程序從URL路徑的格式查找用戶id`/user/{userId}`.

你能夠很容易地將參考路徑變量的模式.例如,若是你有一個Bean的名稱「webSecurity」包含如下:

public class WebSecurity {
		public boolean checkUserId(Authentication authentication, int id) {
				...
		}
}

你能夠參考使用方法:

<http>
	<intercept-url pattern="/user/{userId}/**"
		access="@webSecurity.checkUserId(authentication,#userId)"/>
	...
</http>

或在Java配置

http
		.authorizeRequests()
				.antMatchers("/user/{userId}/**").access("@webSecurity.checkUserId(authentication,#userId)")
				...

在這兩個配置相匹配的url將經過path變量(和)轉換成checkUserId方法.

例如,若是這個URLs是 /user/123/resource,id是123.

Method Security Expressions

方法安全性是一個更復雜的比一個簡單的規則容許或拒絕,Spring Security 3.0介紹了一些新的註釋,以便全面支持表達式的使用.

@Pre and @Post Annotations

有四個屬性註釋支持表達式容許pre和post-invocation受權檢查並提交支持過濾收集參數或返回值.他們是@PreAuthorize@PreFilter@PostAuthorize and @PostFilter. 它們的使用是經過「global-method-security」名稱空間的元素:

<global-method-security pre-post-annotations="enabled"/>
使用@PreAuthorize和@PostAuthorize訪問控制,最明顯的是有用的註釋是「@PreAuthorize」決定是否能夠被調用方法。例如(從"Contacts"示例應用程序)
@PreAuthorize("hasRole('USER')")
public void create(Contact contact);

這意味着用戶與角色"ROLE_USER"纔會容許訪問.顯然一樣的事情能夠很容易地經過使用傳統的配置和一個簡單的配置屬性所需的角色:

@PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);

這裏咱們使用一個方法參數的表達式來決定當前用戶是否有"admin"容許給定的接觸。內置的hasPermission()表達式是經過應用程序上下文連接到Spring Security ACL模塊,see below,你能夠訪問任何變量名稱做爲方法參數的表達式.

有不少方式Spring Security能夠解決方法參數。Spring Security使用DefaultSecurityParameterNameDiscoverer發現參數名稱。默認狀況下,下列選項嘗試方法做爲一個總體.

  • 若是Spring Security的@P註釋存在一個參數的方法,將使用價值。這是使用JDK JDK 8以前有用的接口,編譯不包含任何有關參數名稱的信息。例如:

    import org.springframework.security.access.method.P;
    
    ...
    
    @PreAuthorize("#c.name == authentication.name")
    public void doSomething(@P("c") Contact contact);

    在幕後使用使用「AnnotationParameterNameDiscoverer」可實現自定義支持value屬性指定的任何註釋.

  • 若是Spring Data'的@Param註釋存在至少一個參數的方法,將使用價值。這是使用JDK JDK 8以前有用的接口,編譯不包含任何有關參數名稱的信息。例如:

    import org.springframework.data.repository.query.Param;
    
    ...
    
    @PreAuthorize("#n == authentication.name")
    Contact findContactByName(@Param("n") String name);

在幕後使用使用「AnnotationParameterNameDiscoverer」可實現自定義支持value屬性指定的任何註釋.

  • 若是JDK 8是用來編譯源參數的參數和使用Spring 4+,那麼標準JDK反射API用於發現參數名稱。這包含兩類和接口工做.

  • 最後,若是代碼編譯與調試符號,參數名稱將被發現使用調試符號。這不會爲接口工做,由於他們沒有調試信息參數名稱。爲接口,必須使用註釋或JDK 8的方法.

任何Spring-EL功能可在表達,因此你也能夠訪問屬性參數。舉個例子,若是你想要一個特定方法只容許一個用戶訪問的用戶名匹配的接觸,你能夠寫

@PreAuthorize("#contact.name == authentication.name")
public void doSomething(Contact contact);

咱們訪問另外一個內置的表情, authentication,也就是 Authentication存儲在安全上下文。您也能夠直接訪問它的principal屬性,使用表達式principal。值每每會是一個「UserDetails」實例,因此你可能會使用一個表達式principal.username或「principal.enabled」.

通常,您可能但願執行訪問控制檢查方法調用以後。這能夠經過使用@PostAuthorize註釋.訪問一個方法的返回值,使用內置的名字「returnObject」的表示

過濾用@PreFilter and @PostFilter

正如你可能已經知道,Spring Security支持集合和數組的過濾,這能夠經過使用表達式。這是最多見的一個方法的返回值上執行。例如

@PreAuthorize("hasRole('USER')")
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
public List<Contact> getAll();

當用@PostFilter 註釋,Spring Security遍歷返回的集合並刪除任何元素提供的表達式是錯誤的。「filterObject」指的是當前的對象的集合。你還能夠過濾方法調用以前,使用「@PreFilter」,儘管這是一個不太常見的需求。語法是相同的,可是若是有一個以上的論證它是一個集合類型而後你必須選擇一個的名字使用「filterTarget」屬性的註釋.

注意,過濾顯然是不能代替調優數據檢索查詢。若是你是過濾大收藏和刪除的條目,那麼這多是低效的.

內置的表達式

有一些內置的表達式具體方法安全,咱們已經看到在上面使用。filterTarget 和returnValue值是很簡單,但使用hasPermission()的表達式權證更仔細的觀察.

許可評估者接口

hasPermission()的表達式是委託給一個實例的PermissionEvaluator.它旨在表達系統和Spring Security的ACL系統之間的橋樑,容許您指定受權約束域對象,基於抽象的權限.沒有顯式的依賴ACL模塊,因此你能夠互換,若是須要另外一個實現。接口有兩個方法:

boolean hasPermission(Authentication authentication, Object targetDomainObject,
							Object permission);

boolean hasPermission(Authentication authentication, Serializable targetId,
							String targetType, Object permission);

這直接映射到可用的版本的表情,除了那第一個參數( Authentication 的對象)是不提供的。首先是在域對象的狀況下,使用的訪問控制,已經加載。而後表達式將返回true,若是當前用戶擁有該對象的批准。第二個版本是用於裝載狀況下,對象不是,可是它的標識符。域對象的抽象的"type"說明符也是必需的,容許加載正確的ACL權限。這從來是對象的Java類,可是這不是必須的,只要符合權限如何加載就能夠.

使用「hasPermission()的表情,必須在您的應用程序上下文配置一個PermissionEvaluator」.這看起來像這樣:

<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<bean id="expressionHandler" class=
"org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
	<property name="permissionEvaluator" ref="myPermissionEvaluator"/>
</bean>

在「myPermissionEvaluator」是實現「PermissionEvaluator」bean。一般這將從ACL實現模塊叫作「AclPermissionEvaluator」。見"Contacts"示例應用程序配置更多的細節.

方法安全性元註釋

你能夠使用元數據註釋方法安全性提升代碼的可讀性。

若是你發現你是在代碼庫重複相同的複雜表達式。尤爲方便

例如,考慮如下幾點

@PreAuthorize("#contact.name == authentication.name")

Instead of repeating this everywhere, we can create a meta annotation that can be used instead.

@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("#contact.name == authentication.name")
public @interface ContactPermission {}

元註釋可用於任何Spring安全方法的安全註釋.

爲了保持符合jsr - 250規範的註釋不支持元註釋.

額外的話題

在本部分中,咱們將介紹功能,這須要一個前一章節的知識以及一些更高級的和不常使用的功能框架。

域對象的安全(acl)

概述

複雜的應用須要的每每不是簡單的獲得在web請求或方法調用級別來定義訪問權限。而是,安全決議須要包括誰(認證),其中(的MethodInvocation)和什麼(一些領域對象)。換句話說,受權決策還須要考慮一個方法調用的實際域對象實例的主題。

想象你正在設計申請寵物診所。將會有兩個主要基於spring的應用程序的用戶組:寵物診所的工做人員,以及寵物診所的客戶。員工將得到的全部數據,而你的客戶只能看到本身的客戶記錄。使它更有趣,你的客戶可讓其餘用戶看到他們的客戶記錄,例如"puppy preschool"的導師或當地的"Pony Club"的總統。使用Spring安全爲基礎,有幾種方法能夠使用:

  • 寫下你的業務方法執行的安全。你能夠諮詢一個集合內的Customer域對象實例來肯定哪些用戶能夠訪問。經過使用SecurityContextHolder.getContext().getAuthentication(),你將可以訪問Authentication的對象.

  • 寫一個 AccessDecisionVoter執行的安全GrantedAuthority[]存儲在Authentication對象。這將意味着你的AuthenticationManager須要填充的Authentication自定義GrantedAuthority[]表明每個Customer訪問域對象實例.

  • 寫一個AccessDecisionVoter 執行安全和直接打開目標客戶的域對象。這將意味着你的選民須要訪問一個DAO,容許它來檢索Customer 的對象。它將訪問的Customer 對象的集合的批准用戶和作出適當的決定.

每個這些方法是徹底合法的。然而,第一對受權檢查你的業務代碼。主要問題包括加強的困難的單元測試和重用會更困難的Customer受權邏輯。得到「GrantedAuthority[]的從Authentication對象也很好,但不會擴展到大量的Customer。若是用戶能夠訪問5000`Customer`(不可能在這種狀況下,但試想一下,若是它是一個受歡迎的獸醫大小馬俱樂部!)所需的內存消耗和時間來構造對象將是不受歡迎的Authentication。最後的方法,直接從外部代碼打開Customer,多是最好的三個。實現關注點分離,不濫用內存或CPU週期,但它仍然是低效的,「AccessDecisionVoter」和最終的商業方法自己將執行調用DAO負責檢索AccessDecisionVoter對象。兩個訪問每一個方法調用顯然是不可取的。此外,每一個方法列出你須要編寫本身的訪問控制列表(ACL)從頭持久性和業務邏輯.

幸運的是,還有另外一個選擇,咱們下面會講到.

關鍵概念

Spring Security的ACL服務運送spring-security-acl-xxx.jar.您須要將這個JAR添加到類路徑中使用Spring安全域對象實例的安全功能.

Spring Security的域對象實例的安全能力中心的概念一個訪問控制列表(ACL)。每一個域對象實例系統中有本身的ACL,和ACL記錄的細節,誰能和不能使用域對象。有鑑於此,Spring Security提供三個主要ACL-related功能應用程序:

  • 一種有效地檢索ACL條目你全部的域對象(和修改ACL).

  • 確保給定的方式主要是容許的工做與你的對象,以前被稱爲方法.

  • 確保給定的方式主要是容許使用對象(或者他們返回),後被稱爲方法.

第一個要點,Spring Security ACL的的一個主要功能模塊提供了一個高性能的方式檢索ACL。這個ACL庫能力是極其重要的,由於每個域對象實例系統中可能有多個訪問控制條目,而且每一個ACL可能繼承其餘樹形結構中的ACL(這是開箱即用的支持由Spring Security,很是經常使用)。Spring Security的ACL能力都是被仔細設計以提供高性能檢索ACL,加上可插入的緩存,deadlock-minimizing數據庫更新、獨立於ORM框架(咱們直接使用JDBC),適當的封裝,和透明的數據庫更新.

給定數據庫ACL的操做模塊的核心,讓咱們探索使用四個主要表的默認實現。下面表的大小在一個典型的Spring Security ACL部署,最後列出的錶行:

  • ACL_SID容許咱們惟一地標識系統中的任何本金或權威("SID" 表明"security identity")。惟一列ID、文本表示的SID,國旗代表是否文本表示是指主體名稱或GrantedAuthority.所以,有一個爲每一個獨特的主體或GrantedAuthority行。的上下文中使用時得到許可,SID一般稱爲"recipient".

  • ACL_CLASS容許咱們惟一地標識系統中任何域對象類。只列ID和Java類名。所以,有一行咱們但願每個獨特的類存儲ACL權限.

  • ACL_OBJECT_IDENTITY門店信息系統中每一個獨特的域對象實例。列包含ID,ACL_CLASS表的外鍵,因此咱們知道惟一標識符ACL_CLASS實例咱們提供信息,父,ACL_SID表的外鍵表示域對象實例的全部者,以及咱們是否容許ACL條目繼承任何父ACL。咱們已經爲每一個域對象實例一行咱們存儲ACL權限.

*最後,ACL_ENTRY存儲我的權限分配給每一個收件人。ACL_OBJECT_IDENTITY列包括一個外鍵,收件人ACL_SID(外鍵),是否咱們將審計,整數位屏蔽表明實際的權限被授予或拒絕。咱們爲每一個收件人接收一行容許使用一個域對象.

如最後一段中所述,ACL系統使用整數位屏蔽。別擔憂,你不須要知道的細微之處,轉向使用ACL系統,可是我想說的是,咱們有32位咱們能夠打開或關閉。每個位表明一個許可,並默認權限閱讀(0),寫(1),建立(2)、刪除(第3位)和管理(4)。很容易實現本身的「許可」實例若是你但願使用其餘權限,和其他的ACL框架將沒有知識的擴展.

重要的是要理解,域對象的數量在系統徹底沒有影響咱們選擇使用整數位屏蔽。雖然你有32位用於權限,你能夠有數十億的域對象實例(這將意味着數十億行ACL_OBJECT_IDENTITY並且極可能ACL_ENTRY)。咱們這一點,由於咱們發現有時人們錯誤地認爲他們須要一點對於每個可能的域對象,這並不是如此.

如今咱們已經提供了一個基本的概述ACL系統作什麼,看起來在一個表結構,讓咱們探索的關鍵接口。關鍵接口:

  • Acl:每個域對象都有且只有一個Acl的對象,內部持有AccessControlEntry的年代以及知道的Acl的全部者。Acl不直接引用到域對象,而是一個ObjectIdentity.Acl的存儲在ACL_OBJECT_IDENTITY表.

  • AccessControlEntry:一個Acl擁有多個「AccessControlEntry」年代,一般縮寫爲ace框架。每一個ACE是指一個特定的元組的「許可」,「Sid」和「Acl」。ACE還能夠授予或non-granting和包含審計設置。ACE ACL_ENTRY表中存儲。

  • Permission:權限表明一個特定不變的位元遮罩,爲鑽頭提供了便利的函數屏蔽和輸出信息。上面給出的基本權限(字節0到4)中包含「BasePermission」類。

  • Sid:ACL模塊須要指校長和「GrantedAuthority[]的年代。提供了一個間接層的Sid的界面,這是一種「安全標識」的縮寫。常見的類包括「PrincipalSid」(表明校長在一個「身份驗證」對象)和「GrantedAuthoritySid」。安全身份信息存儲在ACL_SID表。

  • ObjectIdentity:每一個域對象內部ACL表示模塊由一個「ObjectIdentity」。默認實現叫作「ObjectIdentityImpl」。

  • AclService:檢索Acl的適用於一個給定的「ObjectIdentity」。包括實現(JdbcAclService),檢索操做委託給一個「LookupStrategy」。「LookupStrategy」爲檢索ACL信息提供了一個高度優化的策略,使用「(BasicLookupStrategy」批處理檢索)和支持自定義實現利用物化視圖,分級查詢和performance-centric類似,non-ANSI SQL功能。

  • MutableAclService:容許提出了修改Acl的持久性。這並非最重要的若是你不但願使用這個接口。

請注意咱們的開箱即用的AclService和相關數據庫類都使用ANSI SQL.這是主要的數據庫.在寫這篇文章的時候,系統已經成功測試了使用超音速SQL,PostgreSQL,Microsoft SQL Server和Oracle.

兩個樣本船與演示Spring Security ACL模塊。第一個是聯繫人樣本,另外一個是文檔管理系統(DMS)樣本。咱們建議採起一看這些例子.

開始

要開始使用Spring Security ACL的功能,你須要你的ACL信息存儲在某個地方。這須要實例化的DataSource使用Spring。DataSource而後注入JdbcMutableAclServiceBasicLookupStrategy 實例。後者提供高性能的ACL檢索功能,和前提供增變基因功能。指的一個樣本船與Spring Security配置的一個示例。您還須要用四個ACL-specific填充數據庫表中列出的最後一部分(參見ACL樣本的適當的SQL語句).

一旦您建立了所需的模式和實例化JdbcMutableAclService,接下來將須要確保您的域模型支持互操做性的Spring Security ACL包。但願ObjectIdentityImpl 將是足夠的,由於它提供了大量的方法能夠使用它。大部分人都有包含 public Serializable getId()的方法。若是返回類型是長,或兼容長(例如int),你會發現你不須要提供進一步的考慮ObjectIdentity問題。許多地方的ACL模塊依賴長標識符。若是你不使用長(或int,字節等),有一個很是好的機會你須要從新實現的類。咱們不打算支持非long標識符在Spring Security的ACL模塊,多頭已經兼容全部數據庫序列,最多見的標識符的數據類型和長度足夠容納全部常見的使用場景。

如下代碼片斷顯示瞭如何建立一個Acl,或修改現有Acl:

// Prepare the information we'd like in our access control entry (ACE)
ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44));
Sid sid = new PrincipalSid("Samantha");
Permission p = BasePermission.ADMINISTRATION;

// Create or update the relevant ACL
MutableAcl acl = null;
try {
acl = (MutableAcl) aclService.readAclById(oi);
} catch (NotFoundException nfe) {
acl = aclService.createAcl(oi);
}

// Now grant some permissions via an access control entry (ACE)
acl.insertAce(acl.getEntries().length, p, sid, true);
aclService.updateAcl(acl);

在上面的示例中,咱們檢索ACL的44號"Foo" 域對象標識符。咱們添加一個ACE,而後名叫"Samantha"能"administer"的對象。代碼片斷相對明顯,除了insertAce方法。insertAce方法的第一個參數是肯定在什麼位置Acl新條目將被插入。在上面的示例中,咱們只是把新的現有ACE。最後一個參數是一個布爾值指示是否容許或拒絕。大部分時間它將授予(真實的),但若是是否定(假),其實是被屏蔽的權限.

Spring Security並不提供任何特殊的集成自動建立、更新或刪除acl DAO或存儲庫操做的一部分。相反,您須要編寫代碼如上圖所示爲你單獨的域對象.值得考慮使用AOP在服務層與服務層自動把ACL信息操做.咱們發現這在過去的一個至關有效的方法.

一旦你使用上述技術將一些ACL信息存儲在數據庫中,下一步是實際使用ACL信息做爲受權決策邏輯的一部分。這裏有許多選擇。您能夠編寫本身的AccessDecisionVoterAfterInvocationProvider 分別觸發一個方法調用以前或以後。這些課程將使用AclService來檢索相關的ACL,而後調用的ACL。i`Acl.isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode)決定是否授予或拒絕許可。或者,您能夠使用咱們的`AclEntryVoterAclEntryAfterInvocationProvider 或 AclEntryAfterInvocationCollectionFilteringProvider類。全部這些類提供一個declarative-based方法評估ACL信息在運行時,釋放你須要編寫任何代碼。請參閱示例應用程序來學習如何使用這些類。

Pre-Authentication場景

在有些狀況下,您但願使用Spring安全受權,可是用戶已經被一些外部系統可靠地驗證以前訪問應用程序。咱們稱這種狀況爲 "pre-authenticated"場景。例子包括 X.509,Siteminder和身份驗證的Java EE容器的應用程序正在運行。當使用pre-authentication,Spring Security

*識別用戶的請求

*爲用戶得到當局

細節將取決於外部身份驗證機制。用戶可能會被他們的證書信息的X.509,或經過一個HTTP請求頭Siteminder的狀況。若是依靠容器身份驗證,用戶將被調用getUserPrincipal() 的方法傳入的HTTP請求。在某些狀況下,外部機制可能爲用戶提供角色/權威信息但在其餘當局必須得到一個單獨的源,如UserDetailsService.

Pre-Authentication框架類

由於大多數pre-authentication機制遵循相同的模式,Spring Security一組類,提供一個內部框架實現pre-authenticated身份驗證提供者。這個刪除複製和容許添加新的實現結構化的方式,無需寫一切從頭開始。你不須要知道這些類,若是但願使用相似於X.509 authentication,由於它已經有了一個名稱空間配置選項,簡單的使用和開始使用。若是你須要使用顯式的bean配置或計劃編寫本身的實現提供的實現如何工做的理解將是有用的。你會發現類「org.springframework.security.web.authentication.preauth」。咱們在適當的地方提供一個大綱你應該諮詢Javadoc和源.

抽象的預認證處理過濾器

這個類將檢查的當前內容安全上下文,若是空,它將嘗試從HTTP請求中提取用戶信息並提交AuthenticationManager,子類覆蓋如下方法來得到這些信息:

protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);

protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);

把這些後,過濾器將包含返回的數據建立一個PreAuthenticatedAuthenticationToken並提交身份驗證。由"authentication",咱們或許真的只是意味着進一步的處理負荷用戶的部門,而不是按照標準的Spring Security驗證架構。

像其餘Spring安全身份驗證過濾器,pre-authentication過濾器有一個authenticationDetailsSource屬性,默認狀況下將建立一個WebAuthenticationDetails 對象來存儲更多的信息,好比會話標識符和原始IP地址在 Authentication 對象的屬性details。在這種狀況下,用戶角色信息可從pre-authentication獲取機制,數據也存儲在這個屬性,實現GrantedAuthoritiesContainer接口的細節。這使的身份驗證提供者閱讀部門外部分配給用戶。接下來咱們將看一個具體的例子.

基於J2ee的前驗證Web身份驗證源細節

若是過濾器配置了一個authenticationDetailsSource這類的一個實例,權威的信息是經過調用isUserInRole(String role)的一組預先肯定的方法爲每個"mappable roles"配置的類這些來自一個MappableAttributesRetriever.可能的實現包括硬編碼應用程序上下文中的一個列表和閱讀的角色信息<security-role>web.xml文件.pre-authentication示例應用程序使用了後一種方法.

有一個額外的階段(或屬性)的角色被映射到Spring Security GrantedAuthority對象使用一個配置Attributes2GrantedAuthoritiesMapper。默認只會添加一般具有ROLE_前綴的名字,但它讓你徹底控制行爲

前驗證身份驗證提供者

re-authenticated提供者有更多比爲用戶負載的UserDetails對象。它經過委託給一個AuthenticationUserDetailsService.後者是相似於標準UserDetailsService但以一個 Authentication對象而不是用戶名:

public interface AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}

這個接口可能也其餘用途,但pre-authentication它容許訪問官方包裝在「身份驗證」對象,正如咱們在前一節中看到的。PreAuthenticatedGrantedAuthoritiesUserDetailsService這類,或者,它可能表明一個標準的UserDetailsService 經過UserDetailsByNameServiceWrapper 實現.

Http403禁止入口點

AuthenticationEntryPoint是討論的technical overview 一章。一般它負責啓動未通過身份驗證的用戶的身份驗證過程(當他們試圖訪問受保護的資源),可是在pre-authenticated狀況下不適用。你只會配置 ExceptionTranslationFilter與這個類的一個實例,若是你不使用pre-authentication結合其餘身份驗證機制。它將被稱爲AbstractPreAuthenticatedProcessingFilter若是用戶被拒絕的結果在一個空的身份驗證。它老是返回一個「403」錯誤.

具體實現

X.509認證被 own chapter覆蓋.下面咱們來看看一些類,它們提供支持其餘pre-authenticated場景.

請求頭身份驗證(Siteminder)

設置特定的HTTP請求。一個衆所周知的例子是Siteminder,經過用戶名在一個標題叫SM_USER 。這種機制是類 RequestHeaderAuthenticationFilter支持,只是從標題中提取用戶名。它默認使用的名稱SM_USER 做爲標題名稱。看到更多的細節的Javadoc.

注意,當使用這樣的一個系統,框架執行任何身份驗證檢查和extremely重要外部系統的正確配置和保護全部訪問應用程序。若是攻擊者可以僞造原始請求的頭文件沒有被發現以後,他們能夠選擇任何他們但願的用戶名.

Siteminder示例配置

一個典型的配置使用這個過濾器看起來像這樣:

<security:http>
<!-- Additional http configuration omitted -->
<security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</security:http>

<bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="SM_USER"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>

<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
	<bean id="userDetailsServiceWrapper"
		class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
	<property name="userDetailsService" ref="userDetailsService"/>
	</bean>
</property>
</bean>

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>

咱們認爲這裏security namespace是用於配置。還假定您已經添加了一個UserDetailsService(稱爲"userDetailsService")到您的配置加載用戶的角色.

Java EE容器認證

J2eePreAuthenticatedProcessingFilter將從 userPrincipal屬性中提取 HttpServletRequest.使用這個過濾器一般會結合使用Java EE角色如上所述在< < j2ee-preauth-details > >表示.

有一個示例應用程序代碼中使用這種方法,從github獲得的代碼從github,若是你對這些文件感興趣你能夠看下,代碼是在samples/xml/preauth目錄中.

LDAP 身份驗證

概述

LDAP做爲一箇中央存儲庫對用戶信息和身份驗證服務是經常使用的組織.它也能夠用於存儲應用程序用戶的角色信息.這裏有一些不一樣的場景對於如何配置LDAP服務器,所以Spring Security LDAP提供者是徹底可配置的,它使用單獨的策略爲身份驗證和角色接口檢索,並提供默認的實現,能夠配置爲處理各類狀況.在使用以前你應該熟悉Spring Security LDAP.如下連接提供了一個很好的介紹涉及的概念和使用OpenLDAP免費的LDAP服務器創建一個目錄指南http://www.zytrax.com/books/ldap/[http://www.zytrax.com/books/ldap/]. 一些熟悉的JNDI api用於訪問LDAP從Java也多是有用的。咱們在LDAP不使用任何第三方LDAP庫(Mozilla,JLDAP等等),但Spring 的普遍使用是由LDAP,若是你打算添加您本身的定製,對這方面有所瞭解對你的項目多是有用的.

使用LDAP身份驗證時,重要的是要確保你正確配置LDAP鏈接池。若是你不熟悉如何作到這一點,你能夠參考 Java LDAP documentation.

使用LDAP Spring Security

在Spring的LDAP身份驗證安全大體能夠分爲如下幾個階段

  • 得到獨特的LDAP"Distinguished Name",或DN,登陸名。這一般意味着執行搜索的目錄,除非用戶名的具體映射DNs是提早知道。因此用戶可能輸入名稱登陸"joe",但實際LDAP名稱用於驗證將完整的DN,如uid=joe,ou=users,dc=spring,dc=io.

  • 驗證用戶,經過"binding",用戶操做的用戶的密碼與密碼屬性執行遠程"compare" 目錄條目的DN.

  • 加載當局爲用戶的列表.

惟一的例外是當LDAP目錄只是被用於檢索用戶信息並在本地對其進行身份驗證.這個不可能設置有限的讀訪問屬性目錄,如用戶密碼.

下面,咱們將看看一些配置場景。完整的可用配置選項的信息,請查閱安全模式名稱空間(信息應該在XML編輯器中可用).

配置LDAP服務器

你須要作的第一件事是配置的服務器身份驗證應該發生。這是經過使用 <ldap-server> 的元素從安全名稱空間。這能夠配置爲指向外部LDAP服務器,使用的url屬性:

<ldap-server url="ldap://springframework.org:389/dc=springframework,dc=org" />

Using an Embedded Test Server

<ldap-server> 元素也能夠用來建立一個嵌入式服務器,它能夠是很是有用的進行測試和演示。在這種狀況下,你沒有使用它的url屬性:

<ldap-server root="dc=springframework,dc=org"/>

這裏咱們指定目錄是"dc=springframework,dc=org",這是默認的.這種方式,使用名稱空間解析器將建立一個嵌入式Apache目錄服務器的類路徑和掃描任何LDIF文件,它將嘗試加載到服務器。你能夠定製這種行爲使用ldif的屬性,它定義了一個ldif資源加載:

<ldap-server ldif="classpath:users.ldif" />

這使它更容易與LDAP同步,由於它能夠方便工做與外部服務器。它還將用戶從複雜bean配置須要隔離一個Apache鏈接目錄服務器。使用普通的Spring bean配置將會更加混亂。你必需要有必要的Apache Directory依賴性jar用於您的應用程序使用。如LDAP示例應用程序。

使用綁定驗證

這是最多見的LDAP身份驗證場景.

<ldap-authentication-provider user-dn-pattern="uid={0},ou=people"/>

這個簡單的例子將得到用戶的DN替代模式和提供的用戶登陸名試圖綁定,用戶的登陸密碼。若是你全部的用戶都是存儲在單個節點的目錄下這很好,若是您但願配置LDAP搜索篩選器來定位用戶,你能夠使用如下

<ldap-authentication-provider user-search-filter="(uid={0})"
	user-search-base="ou=people"/>

若是使用上面的服務器定義,這將執行搜索在DN ou=people,dc=springframework,dc=org使用user-search-filter 屬性的值做爲一個過濾器。用戶登陸名是代替過濾器的參數名稱,因此它將搜索條目uid屬性等於用戶名。若是user-search-base並不提供,從根搜索.

加載機構

當局是如何從組加載在LDAP目錄中由如下屬性控制

  • group-search-base.定義了目錄樹下的一部分應該執行哪一組搜索。

  • group-role-attribute.屬性包含的名稱定義的權限組條目。默認爲cn

  • 組搜索過濾器。過濾器用於搜索組成員。默認是 uniqueMember={0},對應於groupOfUniqueNames的LDAP類腳註:(注意,這是不一樣於缺省配置底層DefaultLdapAuthoritiesPopulator使用member={0}。]。在這種狀況下,替換參數是用戶的專有名稱。能夠使用參數{1}若是你想過濾的登陸名.

所以,若是咱們使用如下配置

<ldap-authentication-provider user-dn-pattern="uid={0},ou=people"
		group-search-base="ou=groups" />

和通過驗證的成功做爲用戶"ben",隨後的加載下當局將執行搜索的目錄條目的ou=groups,dc=springframework,dc=org,尋找條目包含的屬性uniqueMember價值uid=ben,ou=people,dc=springframework,dc=org。默認的權限名稱前綴ROLE_ 前綴。你能夠改變這個使用 role-prefix屬性。若是你不想要任何前綴,使用role-prefix="none".加載機構的更多信息,請參閱DefaultLdapAuthoritiesPopulator類的Javadoc.

實現類

上面的名稱空間配置選項咱們使用易於使用,更比使用Spring bean簡潔明確。有些狀況下,您可能須要瞭解如何配置Spring Security LDAP直接在您的應用程序上下文。您可能但願定製的一些類的行爲,例如。若是你使用名稱空間配置,那麼你能夠跳過這一節和下一個.

LDAP provider,LdapAuthenticationProvider,實際上並不作太多工做自己,而是表明其餘兩個bean,一個LdapAuthenticator 和一個LdapAuthoritiesPopulator分別負責驗證用戶和檢索用戶的組GrantedAuthority.

Ldap身份驗證明現

authenticator還負責檢索所需的用戶屬性。這是由於權限的屬性可能取決於正在使用的身份驗證類型。例如,若是綁定用戶,與用戶可能須要閱讀的權限有關.

目前有兩種身份驗證策略提供Spring安全:

*直接向LDAP服務器的身份驗證("bind" 身份驗證)。

*密碼比較,用戶提供的密碼是與一個存儲在存儲庫中。這能夠經過檢索密碼屬性的值和檢查本地或經過執行LDAP"compare"操做,提供的密碼在哪裏傳遞到服務器進行比較和真正的密碼值是沒有檢索到.

經常使用功能

以前能夠驗證一個用戶(經過策略),專有名稱(DN)必須從登陸名得到提供給應用程序.這能夠經過簡單的模式匹配(經過設置setUserDnPatterns數組屬性)或經過設置userSearch屬性.對於DN模式匹配方法,格式是使用一個標準的Java模式,將登陸名代替參數{0}.他應該相對於DN模式,配置SpringSecurityContextSource 將綁定到部分(參見connecting to the LDAP server 更多這方面的信息).ldap://monkeymachine.co.uk/dc=springframework,dc=org和有一個模式uid={0},ou=greatapes,"gorilla" 的登陸名將會映射到一個DN`uid=gorilla,ou=greatapes,dc=springframework,dc=org`. 每一個配置的DN模式將嘗試直到找到一個匹配,有關使用搜索的信息,看到部分下面的search objects,結合這兩種方法也能夠使用——模式首先會檢查,若是沒有找到匹配DN,將使用搜索.

綁定認證者

org.springframework.security.ldap BindAuthenticator實現身份驗證綁定驗證策略。它只是試圖將用戶綁定.

身份驗證密碼比較

PasswordComparisonAuthenticator實現了密碼比較驗證策略.

鏈接到LDAP服務器

上面討論的bean必須可以鏈接到服務器。他們都必須提供一個SpringSecurityContextSource這是SpringLDAP的ContextSource的延伸。除非你有特殊要求,您一般會配置一個DefaultSpringSecurityContextSource bean,能夠配置LDAP服務器的URL和可選的"manager"的用戶的用戶名和密碼,使用時將默認綁定到服務器(而不是匿名綁定)。更多信息,讀取這個類的Javadoc和SpringLDAP的AbstractContextSource」.

LDAP搜索對象

一般須要一個比DN-matching定位目錄中的用戶條目更復雜的策略,這能夠封裝在一個LdapUserSearch實例,能夠提供身份驗證明現.例如,讓他們來定位用戶.提供的實現是FilterBasedLdapUserSearch.

濾波器基於Ldap用戶搜索

這個bean使用LDAP目錄中的過濾器匹配用戶對象。Javadoc的過程解釋相應的搜索方法 JDK DirContext class.做爲解釋,搜索篩選器能夠提供參數。這個類,惟一有效的參數是{0}將取代用戶的登陸名.

Ldap當局填充器

驗證用戶成功後,LdapAuthenticationProvider 將試圖經過調用配置LdapAuthoritiesPopulator bean加載一組當局用戶.DefaultLdapAuthoritiesPopulator 是一個實現加載當局經過搜索目錄組的用戶成員(一般這些將groupOfNames」或groupOfUniqueNames加入目錄中的條目)詳細內容,請參閱這個類的Javadoc中它是如何工做的.

若是你只想使用LDAP身份驗證,但加載當局從不一樣來源(好比數據庫),那麼您能夠提供本身的實現這個接口和注入.

Spring Bean 配置

典型的配置中,咱們這裏討論使用一些bean,看起來像這樣:

<bean id="contextSource"
		class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
<property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
<property name="password" value="password"/>
</bean>

<bean id="ldapAuthProvider"
	class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg>
<bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
	<constructor-arg ref="contextSource"/>
	<property name="userDnPatterns">
	<list><value>uid={0},ou=people</value></list>
	</property>
</bean>
</constructor-arg>
<constructor-arg>
<bean
	class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
	<constructor-arg ref="contextSource"/>
	<constructor-arg value="ou=groups"/>
	<property name="groupRoleAttribute" value="ou"/>
</bean>
</constructor-arg>
</bean>

這將設置提供程序訪問LDAP服務器URL`ldap://monkeymachine:389/dc=springframework,dc=org`.身份驗證將由試圖結合DN`uid=<user-login-name>,ou=people,dc=springframework,dc=org`.成功的身份驗證以後,角色分配給用戶經過搜索下的DN`ou=groups,dc=springframework,dc=org`用默認的過濾器(member=<user’s-DN>).角色名稱將從每個"ou"屬性開始匹配.

配置一個用戶搜索對象,使用過濾器(uid=<user-login-name>) 的使用而不是DN-pattern(或補充),您將配置如下bean

<bean id="userSearch"
	class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value=""/>
<constructor-arg index="1" value="(uid={0})"/>
<constructor-arg index="2" ref="contextSource" />
</bean>

並使用它經過設置BindAuthenticator bean的 userSearch屬性.authenticator將調用搜索對象來得到正確的用戶做爲該用戶的DN以前綁定.

LDAP Attributes and Customized UserDetails

身份驗證使用LdapAuthenticationProvider 的最終結果是同樣的一個正常的Spring安全身份驗證使用標準的UserDetailsService界面。建立一個UserDetails」對象並返回存儲在Authentication」對象。做爲UserDetailsService使用,一個常見需求是可以定製這個實現和添加額外的屬性。當使用LDAP,這些一般會從用戶條目屬性。UserDetails對象的建立是由提供者的UserDetailsContextMapper策略,負責從LDAP上下文映射用戶對象和數據:

public interface UserDetailsContextMapper {

UserDetails mapUserFromContext(DirContextOperations ctx, String username,
		Collection<GrantedAuthority> authorities);

void mapUserToContext(UserDetails user, DirContextAdapter ctx);
}

惟一重要的是第一個方法進行身份驗證。若是您提供該接口的一個實現,它注入LdapAuthenticationProvider,你可以控制如何建立UserDetails對象。Spring 的第一個參數是一個實例LDAP的DirContextOperations可讓你接觸的LDAP屬性加載在身份驗證。 username參數是用於驗證和最後一個參數是集當局爲用戶加載的配置 LdapAuthoritiesPopulator.

上下文數據加載略有不一樣的方式取決於您正在使用的身份驗證類型。 BindAuthenticator,返回的上下文綁定操做將被用於讀取屬性,不然數據將從配置讀取使用標準的背景下得到ContextSource(當配置搜索來定位用戶,這將是搜索返回的數據對象).

活動目錄的認證

活動目錄支持本身的標準身份驗證選項,和正常的使用模式不適合太明顯與標準LdapAuthenticationProvider.一般執行身份驗證使用域用戶名(user@domain),而不是使用LDAP專有名稱.爲了更簡單,Spring Security 3.1有一個身份驗證提供者是一個典型的定製活動目錄設置.

Active Directory Ldap身份驗證提供者

配置ActiveDirectoryLdapAuthenticationProvider很是簡單。你只須要提供域名和LDAP服務器的URL提供地址腳註:[還能夠得到使用DNS查找服務器的IP地址。當前不支持,可是但願在之後的版本能夠實現)。一個例子配置會看起來像這樣:

<bean id="adAuthenticationProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
	<constructor-arg value="mydomain.com" />
	<constructor-arg value="ldap://adserver.mydomain.com/" />
</bean>
}

注意,不須要指定一個單獨的ContextSource來定義服務器位置- bean是徹底自包含的。用戶名爲sharon,例如,將可以驗證經過輸入用戶名sharon或完整的Active Directory`userPrincipalName`,即 sharon@mydomain.com.用戶的目錄條目將被定位,並可能返回的屬性中使用自定義建立的UserDetails對象(UserDetailsContextMapper能夠被注入爲此,如上所述)。全部與目錄發生交互用戶的身份。沒有一個"manager"用戶的概念.

默認狀況下,用戶當局正在從memberOf 得到用戶輸入的屬性值。政府再分配給用戶能夠使用被定製UserDetailsContextMapper。你也能夠注入一個GrantedAuthoritiesMapper提供者實例來控制政府最終在 Authentication對象.

活動目錄錯誤代碼

默認狀況下,一個失敗的結果將致使一個標準的Spring Security`BadCredentialsException`,若是你設置的屬性convertSubErrorCodesToExceptions 是true, 異常消息將解析試圖提取活性Directory-specific錯誤代碼,提升一個更具體的異常。檢查類Javadoc的更多信息。

JSP 標籤庫

Spring Security有本身的標籤庫提供基本支持訪問安全信息並在jsp應用安全約束.

宣佈Taglib

要使用的任何標籤,必須有安全JSP 標籤庫:

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

受權標籤

這個標籤是用來肯定是否應評估其內容。在Spring Security 3.0中,能夠以兩種方式使用腳註:[遺留的選項從Spring Security 2.0也支持,但不推薦.].第一種方法使用一個web-security expression,access 屬性中指定的標籤,表達式求值將委託給SecurityExpressionHandler<FilterInvocation> 中定義的應用程序(你應該啓用web表達式<http>的名稱空間配置,以確保這個服務是可用的).

<sec:authorize access="hasRole('supervisor')">

此內容將只對用戶可見的"supervisor"權威的< tt > GrantedAuthority < / tt >。

</sec:authorize>

在與Spring Security PermissionEvaluator共同使用時,標籤也能夠用來檢查權限.例如:

<sec:authorize access="hasPermission(#domain,'read') or hasPermission(#domain,'write')">

做爲一個請求屬性命名的"domain",這個內容只會看到讀寫權限對象用戶.

</sec:authorize>

一個常見的需求是隻顯示一個特定的連接,若是用戶其實是容許點擊它。咱們如何能提早肯定事情是否會被容許嗎?這個標籤也能夠在另外一種操做模式,容許您定義一個特定的URL屬性。若是容許用戶調用的URL,而後標記的身體將被評估,不然它將被忽略。因此你可能相似

<sec:authorize url="/admin">

This content will only be visible to users who are authorized to send requests to the "/admin" URL.

</sec:authorize>

在你的程序內使用這個標籤也必須的一個實例WebInvocationPrivilegeEvaluator,若是您正在使用名稱空間,將自動註冊。這是一 個DefaultWebInvocationPrivilegeEvaluator的實例,它建立了一個虛擬網絡提供的URL請求,並調用安全攔截器請求是否會成功或失敗,這容許您表明您定義的訪問控制設置中使用intercept-url聲明<http>的名稱空間配置省去了重複的信息(如所需的角色)在您的jsp.這種方法還能夠加上一個method屬性,提供HTTP方法,更具體的匹配.

布爾結果評估標籤(是否容許或拒絕訪問)經過設置var屬性變量名稱能夠存儲在一個頁面上下文範圍變量,避免複製和從新評估在頁面中的其餘點.

禁用標記受權進行測試

隱藏連接在頁面不防止未經受權的用戶訪問URL。他們能夠直接在瀏覽器中類型,例如,做爲您的測試過程的一部分,您可能想要顯示隱藏領域爲了檢查環節是安全的後端。若是你設置系統屬性 spring.security.disableUISecurity 爲 true,authorize的標籤仍然會跑但不會隱藏其內容,默認狀況下它也會包含<span class="securityHiddenUI">…​</span> 標籤。這容許你顯示"hidden"與一個特定的CSS樣式等內容不一樣的背景顏色。嘗試運行此屬性啓用的"tutorial"示例應用程序,例如.

你也能夠設置spring.security.securedUIPrefixspring.security.securedUISuffix屬性,若是你想改變周圍的文字從默認的跨度標籤(或使用空字符串徹底刪除).若是你想改變周圍文本從默認「跨度」標籤(或使用空字符串徹底刪除它).

身份驗證標記

這個標籤容許訪問當前存儲在安全內 Authentication對象,它直接在JSP中 呈現一個屬性對象.因此,例如,若是principal`屬性的Authentication是Spring Security的UserDetails的對象的一個實例,以後用<sec:authentication property="principal.username" /> 將會顯示當前用戶的名稱.

固然,這種事情沒有必要使用JSP標記,有些人喜歡保持儘量少的邏輯視圖.您能夠在你的MVC控制器訪問Authentication對象(經過調用SecurityContextHolder.getContext().getAuthentication())並將數據直接添加到您的模型渲染的視圖.

The accesscontrollist Tag

這個標記只在使用Spring Security的ACL模塊,它檢查一個以逗號分隔的所需權限指定的域對象.若是當前用戶全部的權限,而後標記的內容將被評估。若是他們不這樣作,它將被忽略.例如

<sec:accesscontrollist hasPermission="1,2" domainObject="${someObject}">

這將顯示用戶在給定對象上的全部權限所表明的值「1」或「2」.

</sec:accesscontrollist>

在程序內容中,權限被傳遞到「PermissionFactory」中定義中定義,將它們轉換爲ACL`Permission`的實例,因此他們支持任何格式工廠,他們不必定是整數,字符串能夠像READWRITE.若是沒有找到PermissionFactory ,將使用DefaultPermissionFactory的一個實例.程序中的「AclService」將被用於加載Acl的實例提供對象.Acl的將調用所需的權限,以檢查是否都是合法的.

這個標籤還支持var屬性,以一樣的方式authorize 的標籤.

csrfInput標籤

若是啓用了CSRF保護,這個標籤插入一個隱藏表單字段的正確名稱和值CSRF保護令牌。若是沒有啓用CSRF保護,這個標籤輸出.對於任何的<form:form> 標籤使用,一般Spring Security自動插入一個CSRF表單字段.但若是因爲某種緣由你不能使用<form:form>,你能夠使用<form:form>更換.

你應該把這個標籤在一個HTML <form></form>形式的塊,一般地方其餘輸入字段.不要將這個標籤放置在一個Spring <form:form></form:form>,block—Spring Security會自動處理 Spring.

<form method="post" action="/do/something">
		<sec:csrfInput />
		Name:<br />
		<input type="text" name="name" />
		...
	</form>

csrfMetaTags標籤

若是啓用了CSRF保護,這個標籤插入元素標記包含CSRF保護令牌表單字段和標題名稱和CSRF保護令牌的值。這些元素標記可用於使用CSRF保護在JavaScript應用程序.

你應該把csrfMetaTags在一個 HTML <head></head> ,一般地方其餘元標記。一旦你使用這個標籤,你能夠使用JavaScript訪問表單字段的名稱,標題名稱.JQuery中使用這個例子使這項任務變得更加簡單.

<!DOCTYPE html>
<html>
	<head>
		<title>CSRF Protected JavaScript Page</title>
		<meta name="description" content="This is the description for this page" />
		<sec:csrfMetaTags />
		<script type="text/javascript" language="javascript">

			var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
			var csrfHeader = $("meta[name='_csrf_header']").attr("content");
			var csrfToken = $("meta[name='_csrf']").attr("content");

			// using XMLHttpRequest directly to send an x-www-form-urlencoded request
			var ajax = new XMLHttpRequest();
			ajax.open("POST", "http://www.example.org/do/something", true);
			ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded data");
			ajax.send(csrfParameter + "=" + csrfToken + "&name=John&...");

			// using XMLHttpRequest directly to send a non-x-www-form-urlencoded request
			var ajax = new XMLHttpRequest();
			ajax.open("POST", "http://www.example.org/do/something", true);
			ajax.setRequestHeader(csrfHeader, csrfToken);
			ajax.send("...");

			// using JQuery to send an x-www-form-urlencoded request
			var data = {};
			data[csrfParameter] = csrfToken;
			data["name"] = "John";
			...
			$.ajax({
				url: "http://www.example.org/do/something",
				type: "POST",
				data: data,
				...
			});

			// using JQuery to send a non-x-www-form-urlencoded request
			var headers = {};
			headers[csrfHeader] = csrfToken;
			$.ajax({
				url: "http://www.example.org/do/something",
				type: "POST",
				headers: headers,
				...
			});

		<script>
	</head>
	<body>
		...
	</body>
</html>

若是不啓用CSRF保護,csrfMetaTags輸出.

Java Authentication and Authorization Service (JAAS) Provider

概述

Spring Security提供一個包能夠將身份驗證請求委託給Java身份驗證和受權服務(JAAS).這個包是在下面詳細討論.

Jaas遠程准入Provider摘要

AbstractJaasAuthenticationProvider提供JAAS AuthenticationProvider實現的基礎.子類必須實現方法,建立了LoginContextAbstractJaasAuthenticationProvider有許多依賴關係,下面討論它

JAAS回調處理程序

大多數JAAS LoginModule的年代須要一個回調。這些回調一般用於得到用戶的用戶名和密碼.

在Spring Security部署中,Spring Security負責這個用戶交互(經過身份驗證機制),所以,當委託到JAAS身份驗證請求,Spring安全的身份驗證機制已經徹底填充一個身份驗證的對象包含全部所需的JAAS LoginModule的信息.

所以,爲Spring Security JAAS包提供了兩個默認回調處理程序,JaasNameCallbackHandlerJaasPasswordCallbackHandler.每個回調處理程序實現JaasAuthenticationCallbackHandler.在大多數狀況下,這些回調處理程序能夠簡單地使用不了解內部力學.

對於那些須要徹底控制回調行爲,內部AbstractJaasAuthenticationProviderInternalCallbackHandler 包裝這些JaasAuthenticationCallbackHandler.InternalCallbackHandler是類實現JAAS正常的CallbackHandler接口。任什麼時候候使用JAAS LoginModule的,它是經過一個應用程序上下文列表配置InternalCallbackHandler年代。若是LoginModule的請求一個回調兌InternalCallbackHandler,回調是循序傳遞到JaasAuthenticationCallbackHandler被包裝.

JAAS受權授與者

JAAS和主程序一塊兒工做。甚至"roles"在JAAS表示爲主體,Spring Security, 另外一方面, 與Authentication對象,每一個Authentication對象包含一個校長,和多個GrantedAuthority .促進這些不一樣概念之間的映射,Spring Security的JAAS包包括一個AuthorityGranter接口.

AuthorityGranter 負責檢查JAAS並返回一組字符串的,表明權利分配給主程序.對於每個權威返回字符串.爲每一個字符串,返回權威AbstractJaasAuthenticationProvider建立了一個「JaasGrantedAuthority」(實現Spring Security的GrantedAuthority 接口)包含字符串和JAAS程序AuthorityGranter經過.AbstractJaasAuthenticationProvider得到JAAS,首先成功地驗證用戶的使用JAAS LoginModule的憑證,而後訪問LoginContext將它返回.調用LoginContext.getSubject().getPrincipals(),與每一個生成的AuthorityGranter主要傳遞給每一個定義爲與AbstractJaasAuthenticationProvider.setAuthorityGranters(List)的內容.

Spring Security不包括任何生產AuthorityGranter,每個JAAS都有一個特定實現的意義。然而,有一個TestAuthorityGranter的單元測試演示了一個簡單的AuthorityGranter實現.

默認Jaas身份驗證提供

DefaultJaasAuthenticationProvider容許將一個JAAS配置的對象注入依賴項。而後使用JAAS配置的注入建立一個LoginContext.這意味着DefaultJaasAuthenticationProvider不綁定任何特定實現的Configuration由於JaasAuthenticationProvider.

在內存配置

爲了使Configuration容易注入一個DefaultJaasAuthenticationProvider, 默認在內存中實現名爲「InMemoryConfiguration」.實現構造函數接受一個Map,每一個鍵表明登陸配置名稱和值表明一個數組AppConfigurationEntry 。若是沒有找到Map映射提供了InMemoryConfiguration還支持一個默認的AppConfigurationEntry對象Array,使用詳情,請參閱「InMemoryConfiguration」的類級別的javadoc.

默認的Jaas身份驗證提供者配置示例

而 InMemoryConfiguration的Spring能夠更詳細配置standarad JAAS配置文件.它在文中 DefaultJaasAuthenticationProviderJaasAuthenticationProvider 更靈活,由於它不依賴默認配置的實現.

使用InMemoryConfiguration配置一個例子DefaultJaasAuthenticationProvider .注意,自定義的「配置」能夠很容易地實現注入DefaultJaasAuthenticationProvider .

<bean id="jaasAuthProvider"
class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
<property name="configuration">
<bean class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
<constructor-arg>
	<map>
	<!--
	SPRINGSECURITY is the default loginContextName
	for AbstractJaasAuthenticationProvider
	-->
	<entry key="SPRINGSECURITY">
	<array>
	<bean class="javax.security.auth.login.AppConfigurationEntry">
		<constructor-arg value="sample.SampleLoginModule" />
		<constructor-arg>
		<util:constant static-field=
			"javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"/>
		</constructor-arg>
		<constructor-arg>
		<map></map>
		</constructor-arg>
		</bean>
	</array>
	</entry>
	</map>
	</constructor-arg>
</bean>
</property>
<property name="authorityGranters">
<list>
	<!-- You will need to write your own implementation of AuthorityGranter -->
	<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</list>
</property>
</bean>

Jaas Provider准入

JaasAuthenticationProvider 假定默認的Configuration的一個實例http://download.oracle.com/javase/1.4.2/docs/guide/security/jaas/spec/com/sun/security/auth/login/ConfigFile.html[ ConfigFile].這種假設是爲了嘗試更新Configuration.JaasAuthenticationProvider使用默認配置的建立LoginContext.

假設咱們有一個JAAS登陸配置文件,/WEB-INF/login.conf, 用下面的內容:

JAASTest {
	sample.SampleLoginModule required;
};

像全部Spring Security beans,JaasAuthenticationProvider經過應用程序上下文配置.下面的定義將對應於上面的JAAS登陸配置文件

<bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<property name="loginConfig" value="/WEB-INF/login.conf"/>
<property name="loginContextName" value="JAASTest"/>
<property name="callbackHandlers">
<list>
<bean
	class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
<bean
	class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/>
</list>
</property>
<property name="authorityGranters">
	<list>
	<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
	</list>
</property>
</bean>

項目運行

若是配置,「JaasApiIntegrationFilter」將試圖運行「JaasAuthenticationToken」上的Subject。這意味着能夠使用訪問Subject:

Subject subject = Subject.getSubject(AccessController.getContext());

這種集成能夠很容易地使用jaas-api-provision配置屬性。當集成遺留或外部依賴JAAS Subject API被填充,這個特性頗有用

CAS 身份驗證

Overview

JA-SIG產生一個企業範圍的單點登陸系統稱爲CAS。與其餘計劃,JA-SIG中央身份驗證服務是開源的,普遍使用,容易理解,平臺獨立,支持代理功能。Spring Security徹底支持ca,並提供了一個簡單的遷移路徑從Spring Security的單個應用程序部署到多個應用程序部署的企業級CAS服務器.

CAS如何工做

而中科院網站包含文檔的細節CAS的體系結構,提出整體概述了Spring Security.Spring Security 3.x支持中科院。在撰寫本文時,還在使用CAS服務器3.4版.

在您的企業,您須要設置一個CAS服務器。CAS服務器只是一個標準的WAR文件,因此設置您的服務器沒有什麼困難。在WAR文件您將定製登陸和其餘單點登陸頁面顯示給用戶.

當部署一個CAS 3.4服務器,您還須要指定一個AuthenticationHandlerdeployerConfigContext.xml包含ca。AuthenticationHandler有一個簡單的方法,該方法返回一個布爾判斷是否一個給定的證書是有效的.你AuthenticationHandler的實現須要連接到某種類型的後端身份驗證存儲庫,如LDAP服務器或數據庫,CAS自己包含許多AuthenticationHandler的協助.當你下載服務器和部署war文件時,它被設置爲成功進行身份驗證的用戶輸入一個密碼匹配他們的用戶名,用於測試.

Spring Security和CAS交互序列

基本的web瀏覽器之間的交互,CAS服務器和春天Security-secured服務以下:

  • web用戶瀏覽服務的公共頁面.CAS或Spring Security不參與。

  • 最終用戶請求一個頁面或者安全bean的使用是安全的。Spring Security的ExceptionTranslationFilter將檢測到AccessDeniedExceptionAuthenticationException.

  • 由於用戶的Authentication的對象(或缺少)引發了AuthenticationException,ExceptionTranslationFilter將調用配置的AuthenticationEntryPoint。若是使用CAS,這將是CasAuthenticationEntryPoint 類.

  • CasAuthenticationEntryPoint會將用戶的瀏覽器重定向到CAS服務器。它也將顯示一個service 參數,這是春天的回調URL安全服務(應用程序)。例如,瀏覽器的URL重定向多是https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Flogin/cas。

  • 用戶的瀏覽器重定向到ca後,他們將提示輸入用戶名和密碼。若是用戶提供了一個會話cookie這代表他們以前登陸的,他們不會被提示從新登陸(這個過程有一個例外,咱們稍後將討論)。中科院將使用PasswordHandler(或果使用CAS 3.0`AuthenticationHandler`)以上討論決定是否用戶名和密碼是有效的。

  • 成功登陸以後,中科院重定向用戶的瀏覽器將回到原來的服務。它還將包括一個ticket參數,這是一個不透明的字符串表明"service ticket".繼續咱們前面的例子中,瀏覽器重定向到URL https://server3.company.com/webapp/login/cas?ticket=ST-0-ER94xMJmn6pha35CQRoZ。

  • 服務的web應用程序中,CasAuthenticationFilter老是偵聽請求/login/cas(這是可配置的,可是咱們將使用默認本介紹)。處理過濾器將構造一個UsernamePasswordAuthenticationToken表明服務票證。校長就等於CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER,同時將服務票證憑據不透明值。這種身份驗證請求將被交給AuthenticationManager配置。

  • AuthenticationManager實現ProviderManager,這是依次配置了 CasAuthenticationProviderCasAuthenticationProvider只響應包含UsernamePasswordAuthenticationToken(如CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER)和CasAuthenticationToken (稍後討論).

  • CasAuthenticationProvider將驗證服務票據使用TicketValidator實現。這一般是一個Cas20ServiceTicketValidator這是一個類包含在CAS客戶端庫。若是應用程序須要驗證代理機票,使用 Cas20ProxyTicketValidator .TicketValidator 發出一個HTTPS請求CAS服務器以驗證服務票證。它可能還包括一個代理回調URL,包括在這個例子:https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Flogin/cas&ticket=ST-0-ER94xMJmn6pha35CQRoZ&pgtUrl=https / /server3.company.com/webapp/login/cas/proxyreceptor。

  • CAS服務器,驗證請求將被接收。若是提供的服務票證匹配服務URL票發行,中科院將提供積極響應XML顯示用戶名。若是任何代理參與身份驗證(下面討論),代理列表中也包含在XML響應。

  • [OPTIONAL] 若是請求CAS驗證服務包括代理回調URL(在pgtUrl 參數),中科院將包括一個 pgtIou字符串在XML響應。這種pgtIou表明一個借據proxy-granting機票。CAS服務器會建立本身的HTTPS鏈接回pgtUrl.這是相互CAS服務器進行身份驗證,聲稱服務URL。HTTPS鏈接將被用來發送一個代理髮放門票最初的web應用程序.例如,https://server3.company.com/webapp/login/cas/proxyreceptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH。

  • Cas20TicketValidator將收到CAS服務器解析XML。它將返回到CasAuthenticationProviderTicketResponse,其中包括用戶名(強制),代理列表(若是有涉及),和proxy-granting票借據(若是請求代理回調)。

  • 接下來的CasAuthenticationProvider將稱之爲CasProxyDecider配置. CasProxyDecider代表代理列表中 TicketResponse是否接受服務。幾個實現提供SpringSecurity:`RejectProxyTickets`,AcceptAnyCasProxy和 NamedCasProxyDecider。這些名字在很大程度上是自解釋的,除了 NamedCasProxyDecider容許List 提供可信的代理。

  • CasAuthenticationProvider將下一個請求的AuthenticationUserDetailsService加載GrantedAuthority 對象,適用於用戶包含在 Assertion.

  • 若是沒有問題,CasAuthenticationProvider構造CasAuthenticationToken包括細節包含在TicketResponseGrantedAuthority.

  • 控制而後返回CasAuthenticationFilter,把CasAuthenticationToken建立安全上下文.

  • AuthenticationException致使用戶的瀏覽器被重定向到原始頁面 (or a custom destination根據配置).

很好,你還在這裏!如今讓咱們看看這是如何配置的

配置客戶案件

因爲Spring Security中科院的web應用程序是很容易.這是假設你已經知道使用Spring安全的基本知識,下面這些是不會再覆蓋。咱們假設基於命名空間的配置使用,根據須要添加在CAS bean。每一個部分創建在前一節。一個完整的CAS sample application能夠在Spring Security樣本找到.

門票遠程准入服務

本節描述如何設置Spring Security驗證Service Tickets。不少時候這都是一個web應用程序須要。您須要添加一個「ServiceProperties」bean到您的應用程序上下文。這表明你的CAS服務:

<bean id="serviceProperties"
	class="org.springframework.security.cas.ServiceProperties">
<property name="service"
	value="https://localhost:8443/cas-sample/login/cas"/>
<property name="sendRenew" value="false"/>
</bean>

service必須等於一個URL,將由CasAuthenticationFilter監控.sendRenew的默認值爲false,但若是應用程序尤爲敏感應該設置爲true.這個參數的做用是告訴CAS登陸服務,一個單點登陸登陸是不可接受的。相反,用戶將須要從新輸入本身的用戶名和密碼來訪問服務.

下面的bean應該配置開始CAS認證過程(假設您正在使用一個名稱空間配置):

<security:http entry-point-ref="casEntryPoint">
...
<security:custom-filter position="CAS_FILTER" ref="casFilter" />
</security:http>

<bean id="casFilter"
	class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>

<bean id="casEntryPoint"
	class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl" value="https://localhost:9443/cas/login"/>
<property name="serviceProperties" ref="serviceProperties"/>
</bean>

CAS操做,ExceptionTranslationFilter必須有它authenticationEntryPoint屬性設置爲CasAuthenticationEntryPoint」bean.這能夠很容易地經過使用 entry-point-ref,是在上面的示例中完成的。CasAuthenticationEntryPoint必須參考的ServiceProperties bean(如上所述),它提供了企業的CAS登陸服務器的URL.就是用戶的瀏覽器重定向.

CasAuthenticationFilter 已經和屬性UsernamePasswordAuthenticationFilter 很是類似(用於基於表單的登陸)。您能夠使用這些屬性來定製諸如認證成功和失敗的行爲.

接下來,您須要添加一個「CasAuthenticationProvider」及其合做者:

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="casAuthenticationProvider" />
</security:authentication-manager>

<bean id="casAuthenticationProvider"
	class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService">
	<bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
	<constructor-arg ref="userService" />
	</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
	<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
	<constructor-arg index="0" value="https://localhost:9443/cas" />
	</bean>
</property>
<property name="key" value="an_id_for_this_auth_provider_only"/>
</bean>

<security:user-service id="userService">
<security:user name="joe" password="joe" authorities="ROLE_USER" />
...
</security:user-service>

CasAuthenticationProvider 使用UserDetailsService實例加載權限用戶,一旦被CAS認證。咱們已經演示了一個簡單的內存設置。注意,CasAuthenticationProvider 並不實際使用密碼進行身份驗證,但它使用當局.

若是你參考How CAS Works 部分beans 是合理的.

這對CAS完成最基本的配置。若是你沒有作任何錯誤,您的web應用程序框架內應該記錄地工做CAS的單點登陸。沒Spring Security 的其餘部分的安全須要關心事實CAS處理身份驗證。在下面幾節中咱們將討論一些更高級的配置(可選).

Single Logout

CAS協議支持單註銷和Spring Security 很容易地添加到您的安全配置。下面是更新Spring Security配置處理單註銷

<security:http entry-point-ref="casEntryPoint">
...
<security:logout logout-success-url="/cas-logout.jsp"/>
<security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
</security:http>

<!-- This filter handles a Single Logout Request from the CAS Server -->
<bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>

<!-- This filter redirects to the CAS Server to signal Single Logout should be performed -->
<bean id="requestSingleLogoutFilter"
	class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="https://localhost:9443/cas/logout"/>
<constructor-arg>
	<bean class=
		"org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout/cas"/>
</bean>

logout元素記錄用戶的本地應用程序,但不與CAS服務器終止會話或任何其餘已經登陸的應用程序。requestSingleLogoutFilter的過濾器將容許 /spring_security_cas_logout請求的url重定向應用程序配置的CAS服務器註銷url。而後CAS服務器將發送一個註銷請求籤署的全部服務.singleLogoutFilter處理單註銷請求經過在靜態Map 查找的HttpSession而後無效.

也許會困惑,爲何logout 元素和singleLogoutFilter是必要的。最佳實踐是在當地註銷以來首次 SingleSignOutFilter只是將HttpSession的存儲在一個靜態的Map,以調用無效。與上面的配置中,註銷的流程是

  • /logout 的用戶請求將記錄用戶的本地應用程序併發送用戶註銷成功頁面。

  • 註銷成功頁面 /cas-logout.jsp’,爲了註銷的全部應用程序應該指導用戶點擊一個連接指向的/logout/cas

  • 當用戶單擊連接時,用戶被重定向到中科院單註銷URL(https://localhost:9443/cas/logout).

  • 在CAS服務器端,CAS單註銷URL而後提交單註銷全部中科院服務的請求。在中科院服務方面,JASIG invaliditing的SingleSignOutFilter處理註銷請求的原始會話。

下一步是添加到你的web.xml中

<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>
	org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
	<param-name>encoding</param-name>
	<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
	org.jasig.cas.client.session.SingleSignOutHttpSessionListener
</listener-class>
</listener>

驗證與CAS無狀態的服務

本節描述如何使用CAS認證服務。換句話說,本節將討論如何創建一個客戶使用服務,與 CAS進行身份驗證。下一節描述瞭如何設置使用CAS無狀態的服務進行身份驗證.

配置CAS得到代理髮放門票

爲了驗證一個無狀態服務,應用程序須要得到一個代理髮放門票(頁面表)。本節描述如何配置Spring Security得到頁面表構建在thencas-st[Service Ticket Authentication] 配置.

第一步是包括ProxyGrantingTicketStorage在你的Spring Security配置。這是用於存儲頁面表所得到CasAuthenticationFilter,這樣他們能夠用來得到代理票。一個示例配置以下所示

<!--
NOTE: In a real application you should not use an in
		memory implementation. You will also want to ensure
		to clean up expired tickets by calling ProxyGrantingTicketStorage.cleanup()
-->
<bean id="pgtStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/>

下一步是更新的CasAuthenticationProvider可以得到代理票。將 Cas20ServiceTicketValidator替換爲一個Cas20ProxyTicketValidatorproxyCallbackUrl應該設置爲一個應用程序將接收頁面表的URL.最後,配置也應該參考ProxyGrantingTicketStorage因此它能夠使用頁面表獲取代理機票。你能夠找到一個例子,

<bean id="casAuthenticationProvider"
	class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
...
<property name="ticketValidator">
	<bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
	<constructor-arg value="https://localhost:9443/cas"/>
		<property name="proxyCallbackUrl"
		value="https://localhost:8443/cas-sample/login/cas/proxyreceptor"/>
	<property name="proxyGrantingTicketStorage" ref="pgtStorage"/>
	</bean>
</property>
</bean>

最後一步是在 ProxyGrantingTicketStorage更新 CasAuthenticationFilter 接受頁面表和存儲。重要的是proxyReceptorUrlproxyCallbackUrl匹配的Cas20ProxyTicketValidator.一個示例配置以下所示

<bean id="casFilter"
		class="org.springframework.security.cas.web.CasAuthenticationFilter">
	...
	<property name="proxyGrantingTicketStorage" ref="pgtStorage"/>
	<property name="proxyReceptorUrl" value="/login/cas/proxyreceptor"/>
</bean>
使用代理調用無狀態服務票

如今Spring Security得到頁面表,您能夠使用它們來建立代理門票能夠用來驗證無狀態的服務,CAS sample applicationProxyTicketSampleServlet包含一個工做示例。能夠找到示例代碼以下:

protected void doGet(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
// NOTE: The CasAuthenticationToken can also be obtained using
// SecurityContextHolder.getContext().getAuthentication()
final CasAuthenticationToken token = (CasAuthenticationToken) request.getUserPrincipal();
// proxyTicket could be reused to make calls to the CAS service even if the
// target url differs
final String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(targetUrl);

// Make a remote call using the proxy ticket
final String serviceUrl = targetUrl+"?ticket="+URLEncoder.encode(proxyTicket, "UTF-8");
String proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8");
...
}

代理身份驗證票

CasAuthenticationProvider 的區分有狀態的和無狀態的客戶。一個有狀態的客戶被認爲是提交CasAuthenticationFilterfilterProcessUrl.無狀態的客戶的任何一個身份驗證請求CasAuthenticationFilterfilterProcessUrl另外一個URL更好.

由於遠程協議沒有辦法展現本身的HttpSession,它不可能依賴於默認的作法將安全上下文存儲在會話請求之間。此外,因爲CAS服務器無效罰單後,在後續請求中驗證了TicketValidator呈現相同的代理機票不會工做.

一個顯而易見的選擇是爲遠程協議客戶不使用CAS。然而,這將消除許多CAS。做爲一箇中間立場,CasAuthenticationProvider使用StatelessTicketCache.這是僅用於無狀態的客戶主要使用等於CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.發生了什麼是CasAuthenticationProvider將存儲產生的CasAuthenticationToken放在StatelessTicketCache,鍵控代理機票。所以,遠程協議客戶能夠呈現相同的代理機票和 CasAuthenticationProvider不須要接觸CAS服務器進行驗證(除了第一個請求)。一旦驗證,除了最初的目標服務代理機票能夠用於url.

本節創建在前面幾節容納代理機票驗證.第一步是指定驗證全部工件以下所示

<bean id="serviceProperties"
	class="org.springframework.security.cas.ServiceProperties">
...
<property name="authenticateAllArtifacts" value="true"/>
</bean>

下一步是指定servicePropertiesauthenticationDetailsSourceCasAuthenticationFilter。「serviceProperties」屬性指示 CasAuthenticationFilter嘗試全部的工件進行身份驗證,而不是隻有出如今filterProcessUrl.ServiceAuthenticationDetailsSource建立了一個ServiceAuthenticationDetails 確保當前URL,基於HttpServletRequest,用做服務URL時驗證票。方法用於生成服務URL能夠被注入一個自定義定製的AuthenticationDetailsSource ,返回一個自定義ServiceAuthenticationDetails.

<bean id="casFilter"
	class="org.springframework.security.cas.web.CasAuthenticationFilter">
...
<property name="serviceProperties" ref="serviceProperties"/>
<property name="authenticationDetailsSource">
	<bean class=
	"org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
	<constructor-arg ref="serviceProperties"/>
	</bean>
</property>
</bean>

您還須要更新CasAuthenticationProvider處理代理票。將Cas20ServiceTicketValidator替換爲一個Cas20ProxyTicketValidator.您須要配置代理的statelessTicketCache,你想接受。你能夠找到一個例子,下面的更新須要接受全部代理.

<bean id="casAuthenticationProvider"
	class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
...
<property name="ticketValidator">
	<bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
	<constructor-arg value="https://localhost:9443/cas"/>
	<property name="acceptAnyProxy" value="true"/>
	</bean>
</property>
<property name="statelessTicketCache">
	<bean class="org.springframework.security.cas.authentication.EhCacheBasedTicketCache">
	<property name="cache">
		<bean class="net.sf.ehcache.Cache"
			init-method="initialise" destroy-method="dispose">
		<constructor-arg value="casTickets"/>
		<constructor-arg value="50"/>
		<constructor-arg value="true"/>
		<constructor-arg value="false"/>
		<constructor-arg value="3600"/>
		<constructor-arg value="900"/>
		</bean>
	</property>
	</bean>
</property>
</bean>

X.509 Authentication

概述

最經常使用的X.509 證書身份驗證是驗證服務器在使用SSL的身份,從瀏覽器一般在使用HTTPS。瀏覽器會自動檢查服務器證書的已發佈(即數字簽名)的一個受信任的證書頒發機構的列表維護。

您還能夠使用SSL與"mutual authentication";服務器將請求從客戶端做爲一個有效的證書的SSL握手。服務器將驗證客戶端經過檢查其簽署的證書是一個可接受的權威。若是提供了一個有效的證書,它能夠經過servlet API的應用程序。Spring Security X.509模塊提取證書使用一個過濾器。它將證書映射到一個應用程序用戶和加載用戶的組授予機關使用標準的Spring安全基礎設施。

增長X.509認證您的Web應用程序

X.509客戶端身份驗證很是簡單。只是<x509/> 元素添加到您的http安全性名稱空間配置.

<http>
...
	<x509 subject-principal-regex="CN=(.*?)," user-service-ref="userService"/>;
</http>

元素有兩個可選屬性:

  • subject-principal-regex正則表達式用來提取用戶名從證書的主題名稱。上面所示的默認值。這是用戶名,將傳遞給「UserDetailsService」爲用戶負載當局。

  • user-service-ref.這是的bean Id`UserDetailsService`用於x.若是隻有一個定義在應用程序上下文它不須要.

subject-principal-regex應該包含一個組。例如默認表達式"CN=(.*?)," 與常見的名稱字段。若是證書的主題名稱是"CN=Jimi Hendrix, OU=…​",這將給一個用戶名"Jimi Hendrix",不分大小寫。因此"emailAddress=(.?),"匹配"EMAILADDRESS=jimi@hendrix.org,CN=…​"給一個用戶名"jimi@hendrix.org",若是客戶端提供一個證書,成功提取有效的用戶名,而後應該有一個有效的安全上下文中的Authentication對象.若是沒有找到證書,或沒有相應的用戶可能會發現而後安全上下文仍將是空的。這意味着您能夠輕鬆地使用 X.509年與其餘選項,如基於表單的登陸身份驗證.

在Tomcat中設置SSL

有一些證書的samples/certificate的目錄在春季安全項目.您能夠使用這些啓用SSL進行測試若是你不想生成本身的.文件的服務器.jks包含服務器證書、私鑰和發行證書的證書頒發機構.也有一些客戶端證書文件從示例應用程序用戶.你能夠在你的瀏覽器安裝這些啓用SSL客戶機身份驗證.

在SSL支持下tomcat運行,降低的server.jks文件到tomcat的配置的目錄並添加如下鏈接器的`server.xml`l的文件

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
			clientAuth="true" sslProtocol="TLS"
			keystoreFile="${catalina.home}/conf/server.jks"
			keystoreType="JKS" keystorePass="password"
			truststoreFile="${catalina.home}/conf/server.jks"
			truststoreType="JKS" truststorePass="password"
/>

若是你仍然但願SSL鏈接成功clientAuth也能夠被設置爲want,即便客戶沒有提供一個證書。客戶不提供證書將沒法得到的任何對象的訪問Spring Security,除非你使用一個non-X.509認證機制,如表單身份驗證.

run - as驗證替換

概述

AbstractSecurityInterceptor 可以暫時取代Authentication對象在SecurityContextSecurityContextHolder安全對象回調階段。這隻發生若是最初的Authentication 對象是成功處理的AuthenticationManagerAccessDecisionManager.RunAsManager將指示更換Authentication對象,若是有的話,應該使用在SecurityInterceptorCallback.

Configuration

Spring Security提供RunAsManager 接口:

Authentication buildRunAs(Authentication authentication, Object object,
	List<ConfigAttribute> config);

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);

第一個方法返回Authentication對象應該取代現有的身份驗證的對象方法調用的持續時間。若是方法返回null,它代表你沒有更換。第二種方法是使用AbstractSecurityInterceptor 啓動驗證配置屬性的一部分。 supports(Class)的方法被調用以確保安全攔截器將安全對象實現配置的`RunAsManager支持的類型安全攔截器.

一個具體實現RunAsManager提供Spring Security,若是 ConfigAttribute從 RUN_AS_開始,RunAsManagerImpl的類返回一個替代RunAsUserToken.若是找到任何此類ConfigAttribute,替換「RunAsUserToken」將包含相同的主要,憑證,當局爲最初的Authentication對象.伴隨着一個新的GrantedAuthorityImpl 爲每一個RUN_AS_ ConfigAttribute.每個新的GrantedAuthorityImpl將前綴 ROLE_,其次是RUN_AS ConfigAttribute.例如, RUN_AS_SERVER將致使更換RunAsUserToken包含ROLE_RUN_AS_SERVER授予權力.

替代RunAsUserToken就像任何其餘身份驗證的對象。須要驗證的 Authentication ,可能經過一個合適的AuthenticationManager表明團。RunAsImplAuthenticationProvider 執行身份驗證。它只是接受任何有效的 RunAsUserToken .

爲了確保惡意代碼不建立一個RunAsUserToken和如今它保證接受‘RunAsImplAuthenticationProvider,散列鍵存儲在全部生成的令牌. RunAsManagerImplRunAsImplAuthenticationProvider 中建立bean相同的:

<bean id="runAsManager"
	class="org.springframework.security.access.intercept.RunAsManagerImpl">
<property name="key" value="my_run_as_password"/>
</bean>

<bean id="runAsAuthenticationProvider"
	class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
<property name="key" value="my_run_as_password"/>
</bean>

經過使用相同的密鑰,每一個RunAsUserToken能夠驗證它是由一個RunAsManagerImpl批准。出於安全緣由 RunAsManagerImpl創造後是不可變的

Spring Security Crypto模塊

引言

Spring Security Crypto模塊提供了對稱加密,支持密鑰的生成、編碼和密碼。該代碼是分佈式的核心模塊的一部分 但沒有任何其餘Spring Security (或Spring) 代碼的依賴關係。

加密器

加密類提供了構造對稱加密工廠方法,使用這個類 您能夠建立字節加密器加密數據在byte[]形式, 你也能夠構建textencryptors加密文本字符串,且加密是線程安全的。

BytesKeyGenerator

使用encryptors.standard工廠方法構建 "standard" 字節加密機:

Encryptors.standard("password", "salt");

"standard" 採用的加密方法是:256-bit AES using PKCS #5’s PBKDF2 (Password-Based Key Derivation Function #2). 這種方法要求 Java 6. 該密碼用於生成密鑰應存放在安全的地方,不能共享。salt是用來防止在事件中的密鑰對密鑰的字典攻擊,你的加密的數據被泄露 一個16字節的隨機初始化向量也適用,因此每一個加密的消息是惟一的。

所提供的salt應在十六進制編碼的字符串形式,是隨機的,並至少有8個字節的長度。這種salt能夠用keygenerator生成。

String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded

TextEncryptor

使用encryptors.text工廠方法構建一個標準textencryptor:

Encryptors.text("password", "salt");
TextEncryptor使用一個標準的bytesencryptor加密文本數據。加密結果返回爲十六進制編碼的字符串,便於存儲在文件系統或數據庫中。

使用encryptors.queryabletext工廠方法構建一個「可查詢」textencryptor:

Encryptors.queryableText("password", "salt");

一個可查詢的textencryptor和標準textencryptor之間的差別作初始化向量 vector(iv) 處理.iv用於查詢的textencryptor#加密操做是共享的,或不變的,而不是隨機生成的。這意味着同一個文本加密的屢次將始終產生相同的加密結果。這是不太安全的,但須要對加密的數據,須要進行查詢。可查詢加密文本的一個例子是一個OAuth的apikey。

keygenerators

keygenerators類構造密鑰生成器不一樣類型提供了許多便利的工廠方法。 使用這個類,你能夠建立一個byteskeygenerator生成byte[]祕鑰。你也能夠創建一個stringkeygenerator生成字符串鍵。keygenerators線程是安全的。

BytesKeyGenerator

使用keygenerators.securerandom工廠方法生成的實例byteskeygenerator提供支持:

KeyGenerator generator = KeyGenerators.secureRandom();
byte[] key = generator.generateKey();

默認密鑰長度爲8字節.還有一個keygenerators.securerandom變異提供密鑰長度控制:

KeyGenerators.secureRandom(16);

使用keygenerators.shared工廠方法來構建一個byteskeygenerator每次調用,老是返回相同的關鍵:

KeyGenerators.shared(16);

StringKeyGenerator

使用keygenerators.string工廠方法構建一個8字節,提供keygenerator進制編碼,每一個鍵爲字符串:

KeyGenerators.string();

passwordencoders

Spring Security Crypto模塊的密碼包提供了編碼密碼支持. PasswordEncoder 是中心的服務接口,並具備如下簽名:

public interface PasswordEncoder {

String encode(String rawPassword);

boolean matches(String rawPassword, String encodedPassword);
}

若是rawpassword編碼,等於encodedpassword,方法返回true,此方法的目的是支持基於密碼的身份驗證方案。

BCryptPasswordEncoder 實現使用普遍支持的「BCrypt」算法哈希密碼。BCrypt的使用16字節的隨機salt值是故意減慢的算法,以阻礙密碼破解。它能夠使用「強度」參數,從4到31的「強度」參數來調整它的數量。值越高,就必須作更多的工做來計算哈希值。默認值爲10。您能夠在部署的系統中更改此值,而不影響現有的密碼,由於該值也存儲在編碼的散列中

// Create an encoder with strength 16
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
`Pbkdf2PasswordEncoder`實現使用PBKDF2算法哈希密碼。爲了戰勝密碼破解PBKDF2是故意慢的算法,調整須要。用5秒來驗證你的系統上的密碼。
// Create an encoder with all the defaults
Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));

併發支持

在大多數環境中,安全存儲在每個 Thread 基礎. 這意味着當工做是在一個新的 Thread,SecurityContext 失去了 Spring Security provides提供了一些基礎設施,以幫助使這更容 易爲用戶,Spring Security提供了低級別的抽象,用於在多線程環境中使用 Spring Security,事實上,這是Spring Security創建與整合 AsyncContext.start(Runnable) 和 Spring MVC 異步集成.

DelegatingSecurityContextRunnable

最基本的建築塊內Spring Security’s併發支持DelegatingSecurityContextRunnable. 不包委託Runnable爲了初始化的SecurityContextHolder 用指定的SecurityContext爲表明。而後調用委託運行保障明確SecurityContextHolder之後DelegatingSecurityContextRunnable 有些東西看起來就像這樣:

public void run() {
try {
	SecurityContextHolder.setContext(securityContext);
	delegate.run();
} finally {
	SecurityContextHolder.clearContext();
}
}

雖然很簡單,但這使得它無縫的securitycontext從一個線程轉移到另外一個。這很重要,由於,在大多數狀況下,每一個線程的基礎上的securitycontextholder行爲均可能使用了Spring Security的 <global-method-security> 來支持你的服務,你如今能夠很容易地轉移 SecurityContext 當前 Thread到 Thread 調用安全服務。下面是你如何作這件事的一個例子:

Runnable originalRunnable = new Runnable() {
public void run() {
	// invoke secured service
}
};

SecurityContext context = SecurityContextHolder.getContext();
DelegatingSecurityContextRunnable wrappedRunnable =
	new DelegatingSecurityContextRunnable(originalRunnable, context);

new Thread(wrappedRunnable).start();

上面的代碼執行如下步驟:

  • 建立一個Runnable 這是咱們的invoking安全服務,但請注意這是不相關的Spring Security。

  • 得到SecurityContext咱們但願從SecurityContextHolder中初始化DelegatingSecurityContextRunnable

  • 使用DelegatingSecurityContextRunnable建立一個線程。

  • 自從建立了DelegatingSecurityContextRunnableSecurityContextSecurityContextHolder這裏有一個快捷方式的構造函數,下面的代碼與前面的代碼相同:

Runnable originalRunnable = new Runnable() {
public void run() {
	// invoke secured service
}
};

DelegatingSecurityContextRunnable wrappedRunnable =
	new DelegatingSecurityContextRunnable(originalRunnable);

new Thread(wrappedRunnable).start();

咱們有的代碼是簡單使用的,但它仍然須要使用咱們的 Spring Security知識。 在下一節中,咱們將看看咱們如何利用DelegatingSecurityContextExecutor隱藏的因素來使用Spring Security。

DelegatingSecurityContextExecutor

在前面的章節中,咱們發現,它是很容易使用的DelegatingSecurityContextRunnable,但它是不理想,不方便的,由於咱們必須意識到Spring Security 是爲了使用它.讓咱們看看DelegatingSecurityContextExecutor如何能屏蔽咱們的任何代碼知識,若是咱們使用Spring Security.

設計DelegatingSecurityContextExecutor是很是類似於DelegatingSecurityContextRunnable除非它接受委託Executor而不是一個表明Runnable。你能夠看到一個例子,它可能會被用在下面:

SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication =
	new UsernamePasswordAuthenticationToken("user","doesnotmatter", AuthorityUtils.createAuthorityList("ROLE_USER"));
context.setAuthentication(authentication);

SimpleAsyncTaskExecutor delegateExecutor =
	new SimpleAsyncTaskExecutor();
DelegatingSecurityContextExecutor executor =
	new DelegatingSecurityContextExecutor(delegateExecutor, context);

Runnable originalRunnable = new Runnable() {
public void run() {
	// invoke secured service
}
};

executor.execute(originalRunnable);

該代碼執行如下步驟:

  • 建立SecurityContext用於咱們的DelegatingSecurityContextExecutor。請注意,在這個例子中,咱們簡單地手工建立SecurityContext。然而在哪裏或者怎麼獲得並不重要SecurityContext (i.e. 咱們能夠從這裏得到SecurityContextHolder 若是咱們想要)。

  • 建立一個delegateexecutor是在執行提交`Runnable``s

  • 最後咱們建立一個 DelegatingSecurityContextExecutor這是在包裝任何運行,傳遞到執行的方法DelegatingSecurityContextRunnable. 在這個實例中,將包裏的delegateexec運行, SecurityContext 將每個Runnable提交給咱們 DelegatingSecurityContextExecutor. 若是咱們運行後臺任務,須要由一個具備提高權限的用戶運行,這是很是好的,

  • 在這一點上,你可能會問本身 "我該如何保護我所學過的 Spring Security代碼知識?"來代替建立SecurityContext`andthe`DelegatingSecurityContextExecutor 在咱們的代碼中, 咱們能夠注入一個已經初始化的實例DelegatingSecurityContextExecutor.

@Autowired
private Executor executor; // becomes an instance of our DelegatingSecurityContextExecutor

public void submitRunnable() {
Runnable originalRunnable = new Runnable() {
	public void run() {
	// invoke secured service
	}
};
executor.execute(originalRunnable);
}

如今咱們的代碼是不可知的 SecurityContext 正在傳播到Thread,而後originalRunnable 被執行,而後SecurityContextHolder 被清除。在這個示例中,同一個用戶正在被用於執行每一個線程.若是咱們想使用戶從 SecurityContextHolder at the time we invoked executor.execute(Runnable) (i.e. the currently logged in user) 處理 originalRunnable? 是能夠作到的 removing the SecurityContext咱們的爭論是 DelegatingSecurityContextExecutor構造函數,好比:

SimpleAsyncTaskExecutor delegateExecutor = new SimpleAsyncTaskExecutor();
DelegatingSecurityContextExecutor executor =
	new DelegatingSecurityContextExecutor(delegateExecutor);

如今任什麼時候候 executor.execute(Runnable) 執行 SecurityContext 是首先得到的 SecurityContextHolder 而後 SecurityContext 是用來建立 DelegatingSecurityContextRunnable的. 這意味着咱們正在執行的 Runnable 使用相同的用戶來調用 executor.execute(Runnable) 代碼.

Spring Security Concurrency 併發類

指javadoc額外的集成與java併發API和Spring的抽象任務,一旦你理解了之前的代碼你會發現,他們的解釋是很單一的。

  • DelegatingSecurityContextCallable

  • DelegatingSecurityContextExecutor

  • DelegatingSecurityContextExecutorService

  • DelegatingSecurityContextRunnable

  • DelegatingSecurityContextScheduledExecutorService

  • DelegatingSecurityContextSchedulingTaskExecutor

  • DelegatingSecurityContextAsyncTaskExecutor

  • DelegatingSecurityContextTaskExecutor

Spring MVC 整合

Spring Security 本節涵蓋了進一步的細節的集成, 提供了一些可選的集成與Spring MVC

@EnableWebMvcSecurity

Spring Security 4.0, @EnableWebMvcSecurity 是 很差的. 更換 @EnableWebSecurity w這決定將基於加入Spring MVC的特色。

使MVC和Spring Security更好的整合與集成@EnableWebSecurity 對你的配置的註釋。

Spring Security 提供配置使用 Spring MVC’s WebMvcConfigurerAdapter. 這意味着,若是你使用的是更高級的選項,如 WebMvcConfigurationSupport ,那麼你將須要手動提供 Spring Security 配置.

MvcRequestMatcher

Spring Security 提供如何深度整合Spring MVC 匹配的網址和 MvcRequestMatcher. 這是有幫助的,以確保您的Security規則匹配用於處理您的請求的邏輯.

它老是建議提供受權規則匹配的HttpServletRequest和方法的安全性.

經過匹配提供受權規則HttpServletRequest是很好的,由於它很早就發生在代碼路徑,https://en.wikipedia.org/wiki/Attack_surface[attack surface].方法安全性確保若是有人繞過了Web權限規則,您的應用程序仍然是安全的. 這是你該知道的 Defence in Depth

考慮一個控制器映射以下:

@RequestMapping("/admin")
public String admin() {

若是咱們想經過限制訪問該控制器的方法來管理用戶, 一個開發人員能夠經過匹配的 HttpServletRequest 獲得如下的:

protected configure(HttpSecurity http) throws Exception {
	http
		.authorizeRequests()
			.antMatchers("/admin").hasRole("ADMIN");
}

或者在xml中

<http>
	<intercept-url pattern="/admin" access="hasRole('ADMIN')"/>
</http>

任何配置URL /admin將通過身份驗證的用戶做爲管理用戶. 然而, 這取決於咱們 Spring MVC配置, URL /admin.html也會告訴咱們admin() 方法.

問題是,咱們的安全規則只是保護 /admin. 咱們能夠爲全部的排列添加額外的規則 Spring MVC,但這將是至關冗長而乏味的.

相反,咱們能夠利用Spring Security’s MvcRequestMatcher. 下面的配置會保護,Spring MVC將匹配利用Spring MVC匹配URL的URL。

protected configure(HttpSecurity http) throws Exception {
	http
		.authorizeRequests()
			.mvcMatchers("/admin").hasRole("ADMIN");
}

在XML中:

<http request-matcher="mvc">
	<intercept-url pattern="/admin" access="hasRole('ADMIN')"/>
</http>

@AuthenticationPrincipal

Spring Security provides AuthenticationPrincipalArgumentResolver 能解決問題 Authentication.getPrincipal() 對於 Spring MVC 爭論. 經過使用 @EnableWebSecurity 您將自動將此添加到您的 Spring MVC 配置. 若是你使用 XML 基於你的配置, 你必須本身添加這個。例如:

<mvc:annotation-driven>
		<mvc:argument-resolvers>
				<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
		</mvc:argument-resolvers>
</mvc:annotation-driven>

一旦 AuthenticationPrincipalArgumentResolver 是正確配置的,您能夠徹底完成 Spring Security 在Spring MVC層。

考慮一個自定義的狀況 UserDetailsService返回一個 Object 實現 UserDetails 你本身的 CustomUser Object. 和 CustomUser 當前已驗證的用戶能夠使用如下代碼訪問:

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser() {
	Authentication authentication =
	SecurityContextHolder.getContext().getAuthentication();
	CustomUser custom = (CustomUser) authentication == null ? null : authentication.getPrincipal();

	// .. find messags for this user and return them ...
}

至於 Spring Security 3.2 咱們能夠更直接地經過添加註釋來解決這個問題。例如:

import org.springframework.security.core.annotation.AuthenticationPrincipal;

// ...

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@AuthenticationPrincipal CustomUser customUser) {

	// .. find messags for this user and return them ...
}

有時,它多是必要的,以某種方式來改造. 好比, 若是 CustomUser 須要是最終它不能被擴展。 在這種狀況下 UserDetailsService 可能會返回一個 Object 實現 UserDetails並提供了一個命名的方法 getCustomUser 訪問 CustomUser. 好比,他看起來是這個樣子的:

public class CustomUserUserDetails extends User {
		// ...
		public CustomUser getCustomUser() {
				return customUser;
		}
}

而後,咱們能夠訪問 CustomUser 使用 SpEL expression 使用 Authentication.getPrincipal() 做爲根對象:

import org.springframework.security.core.annotation.AuthenticationPrincipal;

// ...

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@AuthenticationPrincipal(expression = "customUser") CustomUser customUser) {

	// .. find messags for this user and return them ...
}

咱們能夠進一步消除咱們的依賴 Spring Security經過標記 @AuthenticationPrincipal 咱們有咱們本身的元註釋註釋. 下面,咱們展現瞭如何咱們能夠這樣作的註釋命名 @CurrentUser.

NOTE:重要的是要認識到消除依賴 Spring Security,它是將建立的消耗應用程序 @CurrentUser. 這一步不是嚴格要求,但有助於隔離你的依賴 Spring Security 到一個更重要的位置.

@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {}

如今@CurrentUser 已指定, 咱們能夠用它來信號來解決咱們的 CustomUser當前已驗證的用戶孤立了咱們依賴 Spring Security 到一個單一的文件.

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@CurrentUser CustomUser customUser) {

	// .. find messags for this user and return them ...
}

Spring MVC 異步集成

Spring Web MVC 3.2+ 有極好的支持 Asynchronous Request Processing. 沒有額外的配置, Spring Security 將自動設置 SecurityContext 到 Thread執行 Callable 由你的控制器返回. 例如,下面的方法將自動有它的 Callable 執行的 SecurityContext 這是可用的,當 Callable 被建立:

@RequestMapping(method=RequestMethod.POST)
public Callable<String> processUpload(final MultipartFile file) {

return new Callable<String>() {
	public Object call() throws Exception {
	// ...
	return "someView";
	}
};
}
Associating SecurityContext to Callable’s

從技術上講, Spring Security 結合 WebAsyncManagerSecurityContext這是用來處理 Callable 是 SecurityContext 存在於 SecurityContextHolder 此時 startCallableProcessing 被調用.

沒有一個自動集成與 DeferredResult由控制器返回. 這是由於 DeferredResult 是由用戶處理的,所以沒有自動整合的方式。 固然, 你依然能夠用 Concurrency Support提供透明的集成與 Spring Security.

Spring MVC 和 CSRF 整合

自動令牌包

Spring Security 將自動 include the CSRF Token 使用形式爲 Spring MVC form tag. 好比說, 下面的 JSP:

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
	xmlns:c="http://java.sun.com/jsp/jstl/core"
	xmlns:form="http://www.springframework.org/tags/form" version="2.0">
	<jsp:directive.page language="java" contentType="text/html" />
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
	<!-- ... -->

	<c:url var="logoutUrl" value="/logout"/>
	<form:form action="${logoutUrl}"
		method="post">
	<input type="submit"
		value="Log out" />
	<input type="hidden"
		name="${_csrf.parameterName}"
		value="${_csrf.token}"/>
	</form:form>

	<!-- ... -->
</html>
</jsp:root>

將輸出HTML,相似於下面的代碼:

<!-- ... -->

<form action="/context/logout" method="post">
<input type="submit" value="Log out"/>
<input type="hidden" name="_csrf" value="f81d4fae-7dec-11d0-a765-00a0c91e6bf6"/>
</form>

<!-- ... -->

解決 CsrfToken

Spring Security 提供 CsrfTokenArgumentResolver 就能自動解決 CsrfToken Spring MVC 爭論. 經過使用 @EnableWebSecurity 您將自動將此添加到您的 Spring MVC 配置. 若是你使用基於XML的配置,您必須本身手動添加.

一旦 CsrfTokenArgumentResolver 是正確配置的,你能夠暴露 CsrfToken 你的靜態HTML爲基礎的應用.

@RestController
public class CsrfController {

	@RequestMapping("/csrf")
	public CsrfToken csrf(CsrfToken token) {
		return token;
	}
}

重要的是要保持 CsrfToken 從其餘域的一個祕密. 這意味着若是你正在使https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS[Cross Origin Sharing (CORS)], 你應該 NOT 暴露 CsrfToken 到任何外部域.

Spring Data 整合

Spring Security 提供 Spring Data整合容許在您的查詢中引用當前的用戶. 它頗有用,但要包括在查詢用戶支持分頁結果因爲過濾後,結果規模不會減小。

Spring 數據 & Spring 安全配置

要使用這種支持,提供一個類型的 SecurityEvaluationContextExtension. 在Java配置中, 他看起來會是這個樣子:

@Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
	return new SecurityEvaluationContextExtension();
}

在XMl配置中, 他看起來會是這個樣子:

<bean class="org.springframework.security.data.repository.query.SecurityEvaluationContextExtension"/>

安全的表達 @Query

現在 Spring Security 能夠在您的查詢中使用,例如:

@Repository
public interface MessageRepository extends PagingAndSortingRepository<Message,Long> {
	@Query("select m from Message m where m.to.id = ?#{ principal?.id }")
	Page<Message> findInbox(Pageable pageable);
}

檢查 Authentication.getPrincipal().getId()看看是否 平等於容器 Message. 請注意,這個示例假定您已定製了一個對象的,該對象是具備一個身份屬性. 經過暴露 SecurityEvaluationContextExtension bean, 全部的Common Security Expressions 可用在 Query.

Appendix

安全數據庫模式

有使用的框架和本附錄提供了一個單一的參考點和給 他們全部的不一樣的數據庫模式. 你只須要爲你須要的部分提供functonality表.

DDL聲明給出了 HSQLDB 數據庫.您能夠使用這些做爲定義您正在使用的數據庫的架構的指導方針.

用戶模式

JDBC 的標準實現了UserDetailsService (JdbcDaoImpl) 須要表加載密碼, 賬戶狀態(可用或者不可用)和權力名單 (角色) 給用戶. 您將須要調整此架構以與您正在使用的數據庫語言相匹配.

create table users(
	username varchar_ignorecase(50) not null primary key,
	password varchar_ignorecase(50) not null,
	enabled boolean not null
);

create table authorities (
	username varchar_ignorecase(50) not null,
	authority varchar_ignorecase(50) not null,
	constraint fk_authorities_users foreign key(username) references users(username)
);
create unique index ix_auth_username on authorities (username,authority);

集團機關

Spring Security 2.0 介紹了當前組支持 JdbcDaoImpl.若是組啓用表,結構以下. 您將須要調整此架構以與您正在使用的數據庫語言相匹配.

create table groups (
	id bigint generated by default as identity(start with 0) primary key,
	group_name varchar_ignorecase(50) not null
);

create table group_authorities (
	group_id bigint not null,
	authority varchar(50) not null,
	constraint fk_group_authorities_group foreign key(group_id) references groups(id)
);

create table group_members (
	id bigint generated by default as identity(start with 0) primary key,
	username varchar(50) not null,
	group_id bigint not null,
	constraint fk_group_members_group foreign key(group_id) references groups(id)
);

請記住,這些表只須要由您使用所提供的JDBC UserDetailsService 實施. 若是你本身寫或選擇實施 AuthenticationProvider 沒有 UserDetailsService,而後只要接口的合同是滿意的,你有完整的自由來存儲的數據。

持續登陸 (記住我) Schema

此表用於存儲更安全的使用的數據 persistent token remember-me 實施. 若是你正在使用 JdbcTokenRepositoryImpl 不管是直接或經過命名空間,您都將須要此表. 請記住調整此架構以與您正在使用的數據庫語言相匹配.

create table persistent_logins (
	username varchar(64) not null,
	series varchar(64) primary key,
	token varchar(64) not null,
	last_used timestamp not null
);

ACL Schema

有四個表所使用 Spring Security ACL 實施.

  1. acl_sid Store身份確認和安全經過ALC系統來保障, 這些能夠適用於惟一的或者多個負責人。

  2. acl_class定義域的對象類型的ACL應用。 class列儲存java類對象名稱。

  3. acl_object_identity 儲存的具體領域對象的標識的定義.

  4. acl_entry 儲存的ACL權限適用於一個特定的對象標識和安全標識。

它假定數據庫將自動生成每一個身份的主鍵。 JdbcMutableAclService 必須可以檢索這些時,它已建立了一個新的行 acl_sid或者 acl_class表。它有兩個屬性定義須要檢索這些值的SQL classIdentityQuery 和 sidIdentityQuery. 這兩個默認 call identity()

ACL加工建立JRC包含在hypersql建立ACL模式的文件 (HSQLDB), PostgreSQL, MySQL/MariaDB, Microsoft SQL Server, and Oracle 數據庫。 這些架構也被證實在如下幾個部分.

HyperSQL

默認架構的工做,採用的是單元測試的框架內嵌入的HSQLDB數據庫.

create table acl_sid(
	id bigint generated by default as identity(start with 100) not null primary key,
	principal boolean not null,
	sid varchar_ignorecase(100) not null,
	constraint unique_uk_1 unique(sid,principal)
);

create table acl_class(
	id bigint generated by default as identity(start with 100) not null primary key,
	class varchar_ignorecase(100) not null,
	constraint unique_uk_2 unique(class)
);

create table acl_object_identity(
	id bigint generated by default as identity(start with 100) not null primary key,
	object_id_class bigint not null,
	object_id_identity bigint not null,
	parent_object bigint,
	owner_sid bigint,
	entries_inheriting boolean not null,
	constraint unique_uk_3 unique(object_id_class,object_id_identity),
	constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),
	constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),
	constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)
);

create table acl_entry(
	id bigint generated by default as identity(start with 100) not null primary key,
	acl_object_identity bigint not null,
	ace_order int not null,
	sid bigint not null,
	mask integer not null,
	granting boolean not null,
	audit_success boolean not null,
	audit_failure boolean not null,
	constraint unique_uk_4 unique(acl_object_identity,ace_order),
	constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
	constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
);

PostgreSQL

create table acl_sid(
	id bigserial not null primary key,
	principal boolean not null,
	sid varchar(100) not null,
	constraint unique_uk_1 unique(sid,principal)
);

create table acl_class(
	id bigserial not null primary key,
	class varchar(100) not null,
	constraint unique_uk_2 unique(class)
);

create table acl_object_identity(
	id bigserial primary key,
	object_id_class bigint not null,
	object_id_identity bigint not null,
	parent_object bigint,
	owner_sid bigint,
	entries_inheriting boolean not null,
	constraint unique_uk_3 unique(object_id_class,object_id_identity),
	constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),
	constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),
	constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)
);

create table acl_entry(
	id bigserial primary key,
	acl_object_identity bigint not null,
	ace_order int not null,
	sid bigint not null,
	mask integer not null,
	granting boolean not null,
	audit_success boolean not null,
	audit_failure boolean not null,
	constraint unique_uk_4 unique(acl_object_identity,ace_order),
	constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
	constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
);

你將不得不分別地設置 classIdentityQuery和 sidIdentityQuery 性能 JdbcMutableAclService 如下的值, :

  • select currval(pg_get_serial_sequence('acl_class', 'id'))

  • select currval(pg_get_serial_sequence('acl_sid', 'id'))

MySQL and MariaDB

CREATE TABLE acl_sid (
	id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	principal BOOLEAN NOT NULL,
	sid VARCHAR(100) NOT NULL,
	UNIQUE KEY unique_acl_sid (sid, principal)
) ENGINE=InnoDB;

CREATE TABLE acl_class (
	id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	class VARCHAR(100) NOT NULL,
	UNIQUE KEY uk_acl_class (class)
) ENGINE=InnoDB;

CREATE TABLE acl_object_identity (
	id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	object_id_class BIGINT UNSIGNED NOT NULL,
	object_id_identity BIGINT NOT NULL,
	parent_object BIGINT UNSIGNED,
	owner_sid BIGINT UNSIGNED,
	entries_inheriting BOOLEAN NOT NULL,
	UNIQUE KEY uk_acl_object_identity (object_id_class, object_id_identity),
	CONSTRAINT fk_acl_object_identity_parent FOREIGN KEY (parent_object) REFERENCES acl_object_identity (id),
	CONSTRAINT fk_acl_object_identity_class FOREIGN KEY (object_id_class) REFERENCES acl_class (id),
	CONSTRAINT fk_acl_object_identity_owner FOREIGN KEY (owner_sid) REFERENCES acl_sid (id)
) ENGINE=InnoDB;

CREATE TABLE acl_entry (
	id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	acl_object_identity BIGINT UNSIGNED NOT NULL,
	ace_order INTEGER NOT NULL,
	sid BIGINT UNSIGNED NOT NULL,
	mask INTEGER UNSIGNED NOT NULL,
	granting BOOLEAN NOT NULL,
	audit_success BOOLEAN NOT NULL,
	audit_failure BOOLEAN NOT NULL,
	UNIQUE KEY unique_acl_entry (acl_object_identity, ace_order),
	CONSTRAINT fk_acl_entry_object FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity (id),
	CONSTRAINT fk_acl_entry_acl FOREIGN KEY (sid) REFERENCES acl_sid (id)
) ENGINE=InnoDB;

Microsoft SQL Server

CREATE TABLE acl_sid (
	id BIGINT NOT NULL IDENTITY PRIMARY KEY,
	principal BIT NOT NULL,
	sid VARCHAR(100) NOT NULL,
	CONSTRAINT unique_acl_sid UNIQUE (sid, principal)
);

CREATE TABLE acl_class (
	id BIGINT NOT NULL IDENTITY PRIMARY KEY,
	class VARCHAR(100) NOT NULL,
	CONSTRAINT uk_acl_class UNIQUE (class)
);

CREATE TABLE acl_object_identity (
	id BIGINT NOT NULL IDENTITY PRIMARY KEY,
	object_id_class BIGINT NOT NULL,
	object_id_identity BIGINT NOT NULL,
	parent_object BIGINT,
	owner_sid BIGINT,
	entries_inheriting BIT NOT NULL,
	CONSTRAINT uk_acl_object_identity UNIQUE (object_id_class, object_id_identity),
	CONSTRAINT fk_acl_object_identity_parent FOREIGN KEY (parent_object) REFERENCES acl_object_identity (id),
	CONSTRAINT fk_acl_object_identity_class FOREIGN KEY (object_id_class) REFERENCES acl_class (id),
	CONSTRAINT fk_acl_object_identity_owner FOREIGN KEY (owner_sid) REFERENCES acl_sid (id)
);

CREATE TABLE acl_entry (
	id BIGINT NOT NULL IDENTITY PRIMARY KEY,
	acl_object_identity BIGINT NOT NULL,
	ace_order INTEGER NOT NULL,
	sid BIGINT NOT NULL,
	mask INTEGER NOT NULL,
	granting BIT NOT NULL,
	audit_success BIT NOT NULL,
	audit_failure BIT NOT NULL,
	CONSTRAINT unique_acl_entry UNIQUE (acl_object_identity, ace_order),
	CONSTRAINT fk_acl_entry_object FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity (id),
	CONSTRAINT fk_acl_entry_acl FOREIGN KEY (sid) REFERENCES acl_sid (id)
);

Oracle Database

CREATE TABLE acl_sid (
	id NUMBER(38) NOT NULL PRIMARY KEY,
	principal NUMBER(1) NOT NULL CHECK (principal in (0, 1)),
	sid NVARCHAR2(100) NOT NULL,
	CONSTRAINT unique_acl_sid UNIQUE (sid, principal)
);
CREATE SEQUENCE acl_sid_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE OR REPLACE TRIGGER acl_sid_id_trigger
	BEFORE INSERT ON acl_sid
	FOR EACH ROW
BEGIN
	SELECT acl_sid_sequence.nextval INTO :new.id FROM dual;
END;

CREATE TABLE acl_class (
	id NUMBER(38) NOT NULL PRIMARY KEY,
	class NVARCHAR2(100) NOT NULL,
	CONSTRAINT uk_acl_class UNIQUE (class)
);
CREATE SEQUENCE acl_class_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE OR REPLACE TRIGGER acl_class_id_trigger
	BEFORE INSERT ON acl_class
	FOR EACH ROW
BEGIN
	SELECT acl_class_sequence.nextval INTO :new.id FROM dual;
END;

CREATE TABLE acl_object_identity (
	id NUMBER(38) NOT NULL PRIMARY KEY,
	object_id_class NUMBER(38) NOT NULL,
	object_id_identity NUMBER(38) NOT NULL,
	parent_object NUMBER(38),
	owner_sid NUMBER(38),
	entries_inheriting NUMBER(1) NOT NULL CHECK (entries_inheriting in (0, 1)),
	CONSTRAINT uk_acl_object_identity UNIQUE (object_id_class, object_id_identity),
	CONSTRAINT fk_acl_object_identity_parent FOREIGN KEY (parent_object) REFERENCES acl_object_identity (id),
	CONSTRAINT fk_acl_object_identity_class FOREIGN KEY (object_id_class) REFERENCES acl_class (id),
	CONSTRAINT fk_acl_object_identity_owner FOREIGN KEY (owner_sid) REFERENCES acl_sid (id)
);
CREATE SEQUENCE acl_object_identity_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE OR REPLACE TRIGGER acl_object_identity_id_trigger
	BEFORE INSERT ON acl_object_identity
	FOR EACH ROW
BEGIN
	SELECT acl_object_identity_sequence.nextval INTO :new.id FROM dual;
END;

CREATE TABLE acl_entry (
	id NUMBER(38) NOT NULL PRIMARY KEY,
	acl_object_identity NUMBER(38) NOT NULL,
	ace_order INTEGER NOT NULL,
	sid NUMBER(38) NOT NULL,
	mask INTEGER NOT NULL,
	granting NUMBER(1) NOT NULL CHECK (granting in (0, 1)),
	audit_success NUMBER(1) NOT NULL CHECK (audit_success in (0, 1)),
	audit_failure NUMBER(1) NOT NULL CHECK (audit_failure in (0, 1)),
	CONSTRAINT unique_acl_entry UNIQUE (acl_object_identity, ace_order),
	CONSTRAINT fk_acl_entry_object FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity (id),
	CONSTRAINT fk_acl_entry_acl FOREIGN KEY (sid) REFERENCES acl_sid (id)
);
CREATE SEQUENCE acl_entry_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
CREATE OR REPLACE TRIGGER acl_entry_id_trigger
	BEFORE INSERT ON acl_entry
	FOR EACH ROW
BEGIN
	SELECT acl_entry_sequence.nextval INTO :new.id FROM dual;
END;

安全空間

本附錄提供了在安全命名空間中可用的元素以及它們建立的基礎上的信息的元素的引用 (個別類的知識,和他們是如何一塊兒工做的,假設你能夠找到項目中的javadoc更多信息和本文檔中的其餘部分)。 若是您之前沒有使用過命名空間,請閱讀這部分。 introductory chapter 對命名空間的配置, 這是做爲一個補充的信息。 使用一個很好的質量的XML編輯器,同時編輯一個基於架構的配置建議,這將提供有關的元素和屬性的上下文信息,以及解釋他們的目的。 命名空間是寫在 RELAX NG 的緊湊的格式,後來轉爲XSD架構. 若是您對這種格式很熟悉,您可能但願檢查它。 schema file 直接。

Web應用安全

<debug>

啓用Spring Security調試基礎設施。這將給人類提供可讀的 (多線) 調試信息以監視安全篩選器的請求. 這可能包括敏感信息,如請求參數或頭文件,而且只在開發環境中使用。

<http>

若是你能使用 <http> 在您的應用程序中的元素 FilterChainProxy bean 叫作 "springSecurityFilterChain"建立和元素內的配置是用來在內部創建一個過濾器鏈 FilterChainProxy. 做爲Spring Security 3.1, 額外的 http 元素能夠用來添加額外的過濾鏈腳註:[ See the introductory chapter 爲你創建映射 web.xml ]. 一些核心過濾器老是在一個過濾器鏈中建立,其餘一些核心過濾器將被添加到堆棧中,這取決於當前的屬性和子元素. 標準過濾器的位置是固定的 (看 the filter order table 在命名空間介紹中,刪除一個與之前版本的框架的常見錯誤源,當用戶在該框架中明確地配置了過濾器鏈時 FilterChainProxybean.若是你須要徹底控制配置的話,你仍然能夠這樣作。

所須要參考全部過濾器 AuthenticationManager將自動注入由命名空間配置建立的內部實例(看到introductory chapter 爲更多的 AuthenticationManager).每一個<http>命名空間塊老是建立一個SecurityContextPersistenceFilter,一個 ExceptionTranslationFilter和一個FilterSecurityInterceptor. 這些都是固定的,不能被替代品替代

<http> 屬性

<http>的屬性元素控制核心過濾器上的一些屬性。

  • access-decision-manager-ref 可選屬性指定的標識 AccessDecisionManager 實現應該用於受權的HTTP請求. 經過一個默認的 AffirmativeBased 實現用於與一個 RoleVoter和 AuthenticatedVoter.

  • authentication-manager-ref 參考的 AuthenticationManager 用來 FilterChain 經過這個HTTP元素建立。

  • auto-config 自動註冊登陸表單,基本認證,註銷服務。若是設置爲「真」,全部這些功能都被添加 (雖然您仍然能夠經過提供相應的元素來自定義每一個元素的配置)。若是未指定,默認爲「假」。不建議使用此屬性。使用明確的配置元素,而不是避免混亂。

  • create-session 控制一個Spring Security類的建立,包括如下:

    • always - Spring Security 若是不存在,將主動建立一個會話。

    • ifRequired -Spring Security只會建立一個會話,若是是必需的 (默認值)。

    • never - Spring Security 永遠不會建立一個會話, 若是是應用程序它將會使用一個會話。

    • stateless - Spring Security 不會建立一個會話,忽略得到一個會話的會話Spring。 Authentication.

  • disable-url-rewriting 防止會話標識被添加到應用程序中的網址。 客戶端必須使用該屬性設置爲 true. 默認值是 true.

  • entry-point-ref 一般狀況下 AuthenticationEntryPoint 使用的將取決於已配置的身份驗證機制。 此屬性容許這種行爲是經過定義一個定製的重寫 AuthenticationEntryPoint bean 這將啓動認證過程。

  • jaas-api-provision 若是可用,運行請求做爲 Subject 得到的 JaasAuthenticationToken這是經過添加一個 JaasApiIntegrationFilter bean 到堆棧。默認值爲 false.

  • name 一個bean標識符,用於指在上下文中的其餘地方的bean.

  • once-per-request 對應於 observeOncePerRequest 財產 FilterSecurityInterceptor. 默認值爲 true.

  • pattern 定義一個模式 http 元素控制將被過濾的請求經過它定義的過濾器列表。解釋是依賴於配置的 request-matcher. 若是沒有定義模式,全部的請求都將被匹配,因此最具體的模式應該首先聲明。

  • realm 設置用於基自己份驗證的域名稱 (若是啓用). 對應於 realmName 財產 BasicAuthenticationEntryPoint.

  • request-matcher 定義 RequestMatcher 戰略中使用的 FilterChainProxy 由 intercept-url建立的bean匹配傳入的請求。 選擇目前 mvcantregex 和 ciRegex, Spring MVC, ant, 正則表達式和不區分大小寫的正則表達式。爲每一個建立一個單獨的實例intercept-url 元素的使用 pattern 和 method 屬性,Ant路徑匹配使用 AntPathRequestMatcher 和正則表達式匹配使用 RegexRequestMatcher. 看到這些類Javadoc詳情究竟如何進行匹配。Ant路徑是默認策略。

  • request-matcher-ref 一個參考到bean的實現 RequestMatcher 這將決定是否 FilterChain應使用, 這是一個更強大的替代。 pattern.

  • security 一個請求模式能夠被映射到一個空的過濾鏈,經過設置這個屬性 none. 沒有安全將被應用,沒有Spring Security的功能將是可用的。

  • security-context-repository-ref 容許注入一個自定義 SecurityContextRepository 進入 SecurityContextPersistenceFilter.

  • servlet-api-provision 提供的版本 HttpServletRequest 安全方法,如 isUserInRole()和 getPrincipal()這是經過添加一個 SecurityContextHolderAwareRequestFilter bean 到堆棧。默認值爲 true.

<access-denied-handler>

此元素容許您設置 errorPage 默認屬性 AccessDeniedHandler 經過使用 ExceptionTranslationFilter,使用 error-page 屬性,或使用該屬性提供您本身的實現。ref屬性。這會在更詳細的章節中討論。 ExceptionTranslationFilter.

父元素 <access-denied-handler>
<access-denied-handler> Attributes
  • error-page 訪問被拒絕頁,一個通過驗證的用戶將被重定向到他們請求的一個沒有權限訪問的頁面。

  • ref 定義一個引用 Spring bean 類型 AccessDeniedHandler.

<cors>

此元素容許配置 CorsFilter. 若是不 CorsFilter或者 CorsConfigurationSource 是指定在Spring MVC類路徑中, a HandlerMappingIntrospector 被用做 CorsConfigurationSource.

<cors> 屬性

<cors>的屬性元素控制頭元素。

  • ref 指定一個指定的名稱的屬性的可選屬性 CorsFilter.

  • ref 指定一個指定的名稱的屬性的可選屬性 CorsConfigurationSource 被注入到一個 CorsFilter 由XML命名空間建立。

父元素 <cors>

<headers>

此元素容許配置額外的 (security) 將發送的標題與響應。 它能夠方便地配置幾個頭文件,也容許經過設置自定義頭 header,能夠發如今 Security Headers 參考截面。

  • Cache-ControlPragma,和 Expires - 能夠設置使用 cache-control元。這將確保瀏覽器不緩存您的安全頁。

  • Strict-Transport-Security - 能夠設置使用 hsts元。這保證了瀏覽器自動請求將來要求HTTPS。

  • X-Frame-Options - 能夠設置使用 frame-options 元 X-Frame-Options 能夠用來阻止clickjacking攻擊。

  • X-XSS-Protection -能夠用來設置 xss-protection元 X-XSS-Protection 能夠經過瀏覽器來作基本的控制。

  • X-Content-Type-Options -能夠用來設置 content-type-options元。 X-Content-Type-Options 標頭防止Internet Explorer MIME嗅探響應從宣佈的內容類型。當下載擴展時這也適用於谷歌瀏覽器。

  • Public-Key-Pinning or Public-Key-Pinning-Report-Only -能夠用來設置 hpkp 元。 這容許攻擊者使用HTTPS的網站經過發佈虛假證書的MIS或抵抗冒充。

  • Content-Security-Policy或 Content-Security-Policy-Report-Only -能夠用來設置 content-security-policy element. Content Security Policy (CSP) 是一種機制,Web應用程序能夠利用減輕內容注入漏洞,如跨站腳本(XSS)。

<headers> 屬性

<headers>的屬性元控制頭元素。

  • defaults-disabled 可選屬性,指定要禁用默認的Spring Security的HTTP響應頭。默認是錯誤的 (包含默認標題)。

  • disabled 可選屬性,指定要禁用Spring Security的HTTP響應頭。默認是錯誤的(標題是啓用的)。

父元素 <headers>

<cache-control>

添加 Cache-ControlPragma, 和 Expires 標頭,以確保瀏覽器不緩存您的安全頁。

<cache-control> 屬性
  • disabled 指定是否禁用緩存控件。默認的錯誤。

父元素 <cache-control>

<hsts>

當能夠添加時 Strict-Transport-Security 對任何安全請求的響應的標頭。這容許服務器指示瀏覽器自動使用HTTPS爲將來的要求。

<hsts> 屬性
  • disabled 指定是否禁用嚴格的傳輸安全性。默認的錯誤。

  • include-sub-domains 指定區域應包括。默認爲true。

  • max-age-seconds 指定時間的主人應該是已知的最大量HSTS主機。默認一年。

  • request-matcher-ref requestmatcher實例若是被用來肯定標題應設置,HttpServletRequest.isSecure()的默認值爲真。

父元素 <hsts>

<hpkp>

當可以添加 Public Key Pinning Extension for HTTP 對任何安全請求的響應的標頭。這容許攻擊者使用HTTPS的網站經過發佈虛假證書的MIS或抵抗冒充。

<hpkp> 屬性
  • disabled 指定HTTP(HPKP)公有鍵應禁用。默認爲true。

  • include-sub-domains 指定區域應包括。默認的錯誤。

  • max-age-seconds 設置公有鍵引腳頭的最大年齡指令的值。默認60天。

  • report-only 指定若是瀏覽器只應報告引腳驗證失敗。默認爲true。

  • report-uri 指定的URI,瀏覽器應該報告PIN驗證失敗。

父元素 <hpkp>

<pins>

引腳列表。

子元素 <pins>

<pin>

指定使用base64編碼SPKI指紋值和加密哈希算法的屬性。

<pin> 屬性
  • algorithm 密碼散列算法。默認是SHA256。

父元素 <pin>

<content-security-policy>

當能夠添加 Content Security Policy (CSP) 響應標頭 CSP 是一種機制,Web應用程序能夠利用減輕內容注入漏洞,如跨站腳本(XSS)。

<content-security-policy> 屬性
  • policy-directives 對於內容安全策略頭文件的安全策略指令(S)或若是報表只設置爲真,則只使用頭文件的內容安全策略報告。

  • report-only 設置爲真,使內容安全策略報告只報告策略違規行爲的標題。默認爲假。

父元素 <content-security-policy>

<frame-options>

當能夠添加 X-Frame-Options header的響應,這會使得瀏覽器作一些安全檢查和預防 clickjacking 攻擊。

<frame-options> 屬性
  • disabled 若是禁用, 且不包括X幀選項報頭,將默認爲錯誤。

  • policy

    • DENY 頁面不能被顯示在一個框架中,不管該網站試圖怎樣作。當指定了幀選項策略時,這仍是默認值。

    • SAMEORIGIN 該頁面只能在同一個頁面上的同一個頁面的框架中顯示。

    • ALLOW-FROM origin 該頁只能顯示在指定的原點的框中。

    換言之,若是你指定了拒絕,不只將試圖加載在一個框架中的頁面失敗時從其餘網站加載,試圖這樣作會失敗,從同一個網站加載。另外一方面,若是你指定的sameorigin,你仍然能夠使用在一個框架網頁只要站點包括在一個框架是做爲一個相同的服務頁面。

  • strategy 選擇 AllowFromStrategy 來使用,當使用allow-from策略時。

    • static 使用一個單一的靜態allow-from價值。該值能夠經過 value屬性.

    • regexp 若是他們被容許使用regelur表達驗證傳入的請求和。正則表達式能夠經過 value 屬性。 用於檢索用於驗證的值的請求參數能夠被使用。 from-parameter.

    • whitelist一個逗號分離含有容許域列表。逗號分隔的能夠經過設置 value屬性。 請求參數用於檢索的值來驗證能夠指定使用的 from-parameter.

  • ref 不是使用一個預約義的策略也能夠使用一個自定義的` allowfromstrategy `。這個bean的引用能夠經過ref屬性指定。

  • value 要使用的值是用allow-from的。 strategy.

  • from-parameter 指定的請求參數的名稱使用時,使用正則表達式或白名單的allow-from策略。

父元素 <frame-options>

<xss-protection>

添加 X-XSS-Protection header 協助防止響應 reflected / Type-1 Cross-Site Scripting (XSS) 攻擊。 這不是一個對XSS攻擊的充分保護!

<xss-protection> 屬性
  • xss-protection-block 當true和XSS啓用保護是真的,增長了mode=block的標頭。這代表該頁面不該該被加載的瀏覽器。當false和XSS啓用保護是真的,頁面仍然會呈現一個反映時檢測到攻擊但反應將被修改以防止攻擊。請注意,有時有辦法繞過這種模式,它能夠常常次使阻塞頁面更可取。

父元素 <xss-protection>

<content-type-options>

添加 X-Content-Type-Options 標頭隨着NOSNIFF值響應。 disables MIME-sniffing對 IE8+谷歌瀏覽器擴展。

<content-type-options> 屬性
  • disabled 若是選擇的指定類型沒法使用,默認FALSE。

父元素 <content-type-options>

<header>

向響應中添加額外的頭文件,須要指定名稱和值。

<header-attributes> 屬性
  • header-name 標頭name 的名字。

  • value value 添加的標頭。

  • ref 引用自定義實現的 HeaderWriter 接口。

父元素 <header>

<anonymous>

添加一個 AnonymousAuthenticationFilter to the stack and an AnonymousAuthenticationProvider. 須要的若是你正在使用 IS_AUTHENTICATED_ANONYMOUSLY 屬性.

父元素 <anonymous>
<anonymous> 屬性
  • enabled 使用默認的命名空間設置,匿名「身份驗證」設施將自動啓用。您能夠使用此屬性禁用它。

  • granted-authority 應分配給匿名請求的授予權限。一般,這是用來分配匿名請求特定的角色,它能夠隨後被用於受權決策。若是未設置,默認爲 ROLE_ANONYMOUS.

  • key 提供者和過濾器之間的密鑰共享。這通常不須要設置。若是未設置,則默認爲一個安全的隨機生成的值。這意味着設置這個值能夠提升啓動時間,當使用匿名功能,由於安全的隨機值能夠須要一段時間才能產生。

  • username 應分配給匿名請求的用戶名。這容許被肯定的主要,這多是重要的日誌記錄和審計。若是未設置,默認爲anonymousUser.

<csrf>將添加元素

http://en.wikipedia.org/wiki/Cross-site_request_forgery[Cross Site Request Forger (CSRF)] protection to the application. It also updates the default RequestCache to only replay "GET" requests upon successful authentication. Additional information can be found in the <<csrf,Cross Site Request Forgery (CSRF)>> section of the reference.
父元素 <csrf>
<csrf>屬性
  • disabled 可選屬性,指定要禁用的Spring Security的CSRF保護。默認值爲假(CSRF保護功能)。這是強烈建議關閉CSRF保護功能。

  • token-repository-ref 使用的csrftokenrepository。默認值是 HttpSessionCsrfTokenRepository.

  • request-matcher-ref requestmatcher實例被用來肯定是否應使用CSRF。除了默認的是「GET」任何HTTP方法,「Trace」、「Head」、「Opitions」。

<custom-filter>

此元素用於將一個過濾器添加到篩選器鏈中。它不會建立任何額外的bean類,但被用來選擇一個類型的bean javax.servlet.Filter已在應用程序上下文中定義,完整的細節能夠在Spring Security維護的篩選器鏈中的特定位置處添加。 namespace chapter.

父元素 <custom-filter>
<custom-filter>屬性
  • after 過濾器自定義過濾後,應放置在鏈中。此功能只須要高級用戶,但願混合本身的過濾器到安全過濾器鏈,並有一些知識的標準Spring Security過濾器。將篩選器名稱映射到特定的Spring Security實現篩選器。

  • before 過濾器應當即在此以前,將自定義篩選器放置在鏈中。

  • position 若是你正在更換一個標準的過濾器。自定義篩選器應放置在鏈中的顯式位置。

  • ref 定義了一個實現的Spring bean的參考 Filter.

<expression-handler>

定義 SecurityExpressionHandler若是啓用基於表達式的訪問控制,則將使用實例,若是默認實現(沒有ACL支持)將用於不提供。

父元素 <expression-handler>
<expression-handler> 屬性
  • ref 定義了一個實現的Spring Security的參考 SecurityExpressionHandler.

<form-login>

用來添加一個UsernamePasswordAuthenticationFilter 到過濾器堆棧和一個 LoginUrlAuthenticationEntryPoint 到應用程序的環境, If no attributes are supplied, a login page will be generated automatically at the URL若是沒有提供屬性,將在網址中自動生成登陸頁 "/login" 腳註:[ 此功能是真的只是提供了方便,並不僅是用於生產 (在那裏,一個視圖技術將被選擇,並能夠用來提供一個自定義的登陸頁面,這個類 DefaultLoginPageGeneratingFilter 是 負責顯示登陸頁面,將正常形式的登陸和/或OpenID若是須要提供登陸形式。 ] 該行爲能夠使用自定義 <form-login> Attributes.

父元素 <form-login>
<form-login> 屬性
  • always-use-default-target 若是設置 true, t用戶將始終從給定的值開始 default-target-url, 何到達登陸頁面。映射到 alwaysUseDefaultTargetUrl 財產 UsernamePasswordAuthenticationFilter. 默認值是 false.

  • authentication-details-source-ref 參考一 AuthenticationDetailsSource將被認證過濾器使用。

  • authentication-failure-handler-ref 能夠做爲一種替代 authentication-failure-url, 給您一個身份驗證失敗後的導航流的徹底控制權。該值應該是一個 AuthenticationFailureHandler bean在應用程序上下文中。

  • authentication-failure-url 映射到 authenticationFailureUrl屬性 UsernamePasswordAuthenticationFilter. 定義瀏覽器將被重定向到登陸失敗的網址。默認值爲 /login?error,自動登陸頁面生成器自動處理,用一個錯誤信息從新繪製登陸頁面。

  • authentication-success-handler-ref 這能夠做爲一種替代default-target-url 和 always-use-default-target, 給您一個成功的認證後的導航流的徹底控制。該值應該是一個 AuthenticationSuccessHandler bean在應用程序上下文中。默認狀況下,實現 SavedRequestAwareAuthenticationSuccessHandler使用和注入 default-target-url.

  • default-target-url 映射到 defaultTargetUrl 特性 UsernamePasswordAuthenticationFilter. 若是沒有設置,默認值是「/」(應用程序的根)。登陸後,用戶將被帶到這個網址,只要他們沒有被要求登陸,且他們試圖訪問一個有抵押的資源,他們將被帶到最初的請求的網址。

  • login-page 應該用來顯示登陸頁面的網址。映射到` loginformurl 特性 `LoginUrlAuthenticationEntryPoint. 默認值爲 "/login".

  • login-processing-url 映射到 filterProcessesUrl 特性 UsernamePasswordAuthenticationFilter。默認值爲 "/login"。

  • password-parameter 包含密碼的請求參數的名稱。默認爲「password」。

  • username-parameter 包含用戶名的請求參數的名稱。默認爲「username」。

  • authentication-success-forward-url 映射到 ForwardAuthenticationSuccessHandlerauthenticationSuccessHandler特性 UsernamePasswordAuthenticationFilter

  • authentication-failure-forward-url 映射到 ForwardAuthenticationFailureHandlerauthenticationFailureHandler 特性 UsernamePasswordAuthenticationFilter.

<http-basic>

添加一個 BasicAuthenticationFilter 和 BasicAuthenticationEntryPoint 對配置。後者將只用於做爲配置入口點,若是未啓用基於窗體的登陸。

父元素 <http-basic>
<http-basic> 屬性
  • authentication-details-source-ref 參考 AuthenticationDetailsSource將使用認證過濾器。

  • entry-point-ref 設置 AuthenticationEntryPoint 用來 BasicAuthenticationFilter.

<http-firewall> 元

實現的頂層元素 HttpFirewall 進入 FilterChainProxy 由命名空間建立,默認實現應該適用於大多數應用程序。

<http-firewall> 屬性
  • ref 定義了一個實現的Spring Bean的參考 HttpFirewall.

<intercept-url>

此元素用於定義應用程序和配置如何處理它們的「網址」模式的集合 ,它被用來構建 FilterInvocationSecurityMetadataSource 經過使用 FilterSecurityInterceptor. 它還負責配置 ChannelProcessingFilter 若是特定的URL須要經過HTTPS訪問,例如。 當匹配指定的模式對傳入的請求時,匹配是在聲明的元素的順序中完成的。因此最具體的匹配模式應該是第一個,最廣泛的應該是最後一個。

父元素 <intercept-url>
<intercept-url> 屬性
  • access 列出將要存儲在該目錄中的訪問屬性 FilterInvocationSecurityMetadataSource 用於定義的網址模式/方法組合。這應該是一個逗號分隔的安全配置屬性(如角色名稱)的列表。

  • filters 只能採起「none」的值,這將致使任何匹配的請求,徹底繞過Spring Security過濾器鏈。沒有其餘的` <HTTP> ` 配置將有影響的請求,將沒有安全上下文可供其持續時間。在請求期間訪問安全方法將失敗。

  • method HTTP方法將使用與模式匹配傳入的請求合併。若是省略,任何方法將匹配。若是一個相同的模式被指定,而沒有一個方法,該方法特定的匹配將優先。

  • pattern 定義了網址路徑的模式。內容將取決於 request-matcher 從包含HTTP元素屬性,因此將默認的Ant路徑語法。

  • requires-channel 「http」或「https」取決於一個特定的URL模式應該訪問的HTTP或HTTPS區別。 lternatively值「any」能夠用來當沒有偏好。若是這個屬性是存在於any <intercept-url> 元, 而後一個 ChannelProcessingFilter 將添加到篩選器堆棧中,並將其添加到應用程序上下文中的附加依賴項添加到。

若是一個 <port-mappings> 配置添加,他將被用於 SecureChannelProcessor 和 InsecureChannelProcessor beans 用來重定向到 HTTP/HTTPS端口.

<jee>

添加到過濾器鏈j2eepreauthenticatedprocessingfilter提供集成容器認證。

父元素 <jee>
<jee> 屬性
  • mappable-roles 逗號隔開要查詢傳入的HttpServletRequest消息的角色列表。

  • user-service-ref 對用戶的服務(或userdetailsservice bean)ID

<logout>

添加一個LogoutFilter 到過濾器堆棧。這是配置一個 SecurityContextLogoutHandler

父元素 <logout>
<logout> 屬性
  • delete-cookies 當用戶登陸時,應刪除的一個逗號分隔的名稱列表。

  • invalidate-session 映射一個invalidateHttpSession的 SecurityContextLogoutHandler. 默認值爲「真」,因此,會話將被做廢註銷。

  • logout-success-url 登陸後用戶將採起目標網址。默認值爲 <form-login-login-page>/?logout (i.e. /login?logout)

    設置此屬性將注入SessionManagementFilter 和一個SimpleRedirectInvalidSessionStrategy配置屬性值。當一個無效的會話ID提交,該戰略將調用重定向到配置的URL。

  • logout-url URL會形成註銷 (i.e. 將由過濾器處理). 默認值爲 "/logout".

  • success-handler-ref 可用於提供一個實例 LogoutSuccessHandler 將被調用來控制日誌記錄後的導航。

<openid-login>

相似於<form-login>,而且具備相同的屬性. login-processing-url的默認值是"/login/openid".OpenIDAuthenticationFilter和 OpenIDAuthenticationProvider 將被註冊. 後者須要去引用一個 UserDetailsService. 一樣, 這樣能夠被 id指定, 使用 user-service-ref 屬性, 或者將在應用程序上下文中被自動定位。

<openid-login>的父元素
<openid-login>的屬性
  • Always-use-the-default-target 用戶應該老是被重定向到登陸後的默認目標網址.

  • authentication-details-source-ref 對將要使用身份驗證過濾引用一個身份驗證詳細信息源

  • authentication-failure-handler-ref 引用一個AuthenticationFailureHandler bean,應用於處理身份驗證失敗的請求.不該該使用與身份驗證失敗的連接組合,實施執行處理導航到後續的目標.

  • authentication-failure-url 登陸失敗頁面的網址.若是沒有指定登陸失敗的網址, Spring Security 將自動建立一個失敗的登陸網址,當請求登陸失敗的網址時會開出登陸錯誤和一個相應的過濾器.

  • authentication-success-forward-url 在UsernamePasswordAuthenticationFilter屬性中將 ForwardAuthenticationSuccessHandler 映射到 authenticationSuccessHandler .

  • authentication-failure-forward-url 在UsernamePasswordAuthenticationFilter屬性中將 ForwardAuthenticationSuccessHandler 映射到 authenticationSuccessHandler .

  • authentication-success-handler-ref 引用一個AuthenticationSuccessHandler bean應用於處理一個成功的身份驗證請求.不該與組合使用. default-target-url (or always-use-default-target) 實現執行是處理導航到後續的目標.

  • default-target-url 若是用戶的前一個動做沒法恢復,將被重定向到成功認證後的URL.一般若是用戶訪問登陸頁面沒有首先要求安全操做,將會觸發身份驗證.若是未指定,默認爲應用程序的根.

  • login-page 登陸頁面URL. 若是沒有指定登陸的URL, Spring Security將自動建立一個登陸網址和一個相應的過濾器,以呈現被請求的登陸網址.

  • login-processing-url 登陸窗口被髮布的網址.若是未被指定,它默認爲登陸.

  • password-parameter 包含密碼的請求參數的名稱。默認爲"password".

  • user-service-ref 參考用戶服務(或用戶詳細信息服務)Id

  • username-parameter 包含用戶名的請求參數的名稱。默認爲 "username".

<openid-login>的子元素

<attribute-exchange>

attribute-exchange元素定義屬性列表應該從身份提供程序中請求. 在OpenID Support 命名空間配置章節的部分能夠找出一個例子. 不僅一個能夠使用, 在這種狀況下每一個必須有 identifier-match 屬性, 對所提供的OpenID標識符匹配包含一個正則表達式. 這容許從不一樣的供應商(Google, Yahoo etc)獲取不一樣的屬性列表 .

<attribute-exchange>的父元素
<attribute-exchange>屬性
  • identifier-match 當決定在身份驗證過程當中使用哪些屬性交換配置,將要與所請求的標識進行比較的正則表達式.

<attribute-exchange>的子元素

<openid-attribute>

用於製造一個OpenID Ax屬性 Fetch Request

<openid-attribute>的父元素
<openid-attribute> 屬性
  • count 指定要返回的屬性的數量。例如,返回3個電子郵件. 默認值是 1.

  • name 指定要返回的屬性的名稱。例如,電子郵件.

  • required 指定此屬性是否被要求對操做,但若是操做不返回屬性,則不出錯。默認爲false.

<port-mappings>

默認狀況下,實例portmapperimpl將被添加到配置中用於安全和不安全的URL重定向到.此元素能夠選擇地用於重寫該類定義的默認映射. 每一個 <port-mapping> 元素定義了一對 HTTP:HTTPS 端口. 默認的映射是80:443和8080:8443.重寫這些的例子能夠在 namespace introduction找到.

<port-mappings>的父元素
<port-mappings>的子元素

<port-mappings>

當強制重定向提供了一個地圖的HTTP端口HTTPS端口方式.

<port-mappings>父元素
<port-mappings> 屬性
  • http HTTP端口使用.

  • https HTTPS端口使用.

<remember-me>

添加 RememberMeAuthenticationFilter到堆棧.根據屬性設置,將依次配置一個 TokenBasedRememberMeServices,一個PersistentTokenBasedRememberMeServices 或用戶指定實現 RememberMeServices .

<remember-me>的父元素
<remember-me> 屬性
  • authentication-success-handler-ref 若是須要自定義導航,在RememberMeAuthenticationFilter上設置authenticationSuccessHandler.在應用程序上下文中該值應該是個` authenticationsuccesshandler ` bean的名稱.

  • data-source-ref 引用一個 DataSource bean. 若是這樣設置,persistenttokenbasedremembermeservices `將使用和配置一個 jdbctokenrepositoryimpl `實例.

  • remember-me-parameter 切換 remember-me認證請求的參數名.默認爲"remember-me". 映射到"parameter"的AbstractRememberMeServices屬性.

  • key AbstractRememberMeServices屬性映射到"key" . ,以確保remember-me cookies 僅在一個應用程序腳註中有效:[這不影響使用 PersistentTokenBasedRememberMeServices, 令牌存儲在服務器端.]. 若是這不是設置一個將產生的安全的隨機值. 由於生成安全的隨機值可能須要一段時間, 當咱們使用remember me功能時,設置一個明確的值能夠改善啓動時間.

  • services-alias 輸出內部定義的 RememberMeServices 做爲 bean 別名,容許它在應用程序上下文中被其它beans使用.

  • services-ref 將被使用的過濾器容許` remembermeservices 徹底控制實施. 值應該是在應用程序上下文中實現此接口的bean的"id". 若是註銷過濾器在使用也應該執行 logouthandler `.

  • token-repository-ref 配置一個 PersistentTokenBasedRememberMeServices 可是容許使用一個自定義的 PersistentTokenRepository bean.

  • token-validity-seconds AbstractRememberMeServices屬性映射到 tokenValiditySeconds . 指定remember-me cookie在幾秒鐘內應是有效的. 默認狀況下,有效期爲14天.

<request-cache> 元素

集將被 ExceptionTranslationFilter使用的 RequestCache實例去存儲在調用AuthenticationEntryPoint前的請求信息.

<request-cache>父元素
<request-cache> 屬性
  • ref 對Spring bean定義一個引用,它是一個 RequestCache.

<session-management>

經過添加一個 SessionManagementFilter 到過濾器棧,Session-management 相關功能時被實施的.

<session-management>父元素
<session-management> 屬性
  • invalid-session-url 設置此屬性將會注入 SessionManagementFilter 一個 SimpleRedirectInvalidSessionStrategy 配置屬性值.當提交一個無效的ID, 該戰略將會被調用到重定向配置的URL.

  • session-authentication-error-url 定義的錯誤頁面應該顯示在sessionauthenticationstrategy引起異常的URL. 若是沒有設置,未經受權的(401)錯誤代碼將返回到客戶端. 請注意,若是錯誤發生在一個基於窗體的登陸,此屬性不適用.在身份驗證失敗的網址將優先.

  • session-authentication-strategy-ref 容許加入被 SessionManagementFilter使用的SessionAuthenticationStrategy 實例.

  • session-fixation-protection 說明會話固定保護的應用將在用戶認證. 若是設置爲"none", 將不會應用保護. "newSession" 將新建一個新的空會話, 只有Spring Security相關屬性遷移. "migrateSession" 將建立一個新的會話,並將全部會話屬性複製到新會話中. In Servlet 3.1 (Java EE 7) 新的容器, 指定「changesessionid」將保持現有的會話和使用容器提供的會話固定保護(HttpServletRequest # changesessionid()).默認爲「changesessionid在Servlet 3.1和新的容器, 「migratesession」在大容器.若是「changesessionid」用於大容器,拋出一個異常.

    若是啓用會話固定保護, ` sessionmanagementfilter 注入一個適當的配置 defaultsessionauthenticationstrategy `.看到這類Javadoc詳情.

<session-management>子元素

<concurrency-control>

添加支持併發會話控制, 容許將限制放置在用戶能夠擁有的活動會話的數量上. 一個` concurrentsessionfilter 將被建立, 而且一個 `ConcurrentSessionControlAuthenticationStrategy 將會可用於 SessionManagementFilter. 若是已聲明 form-login元素,則該策略對象也將被注入到所建立的驗證篩選器中.一個 SessionRegistry(一個除非用戶但願使用一個自定義bean的SessionRegistryImpl實例)將被建立供使用的戰略實例.

<concurrency-control>父元素
<concurrency-control>屬性
  • error-if-maximum-exceeded 若是設置爲"true",當用戶試圖超過容許的最大會話數時,SessionAuthenticationException將會被引起. 這默認的行爲是使一個原始的會話失效.

  • expired-url 若是他們試圖使用一個已被併發會話控制器"expired"的會話,URL用戶將被重定向,由於用戶已經超過了容許的會話數,並在其餘地方再次登陸. 除非 exception-if-maximum-exceeded被設置.若是沒有提供任何值,一個有效消息將直接返回到響應.

  • max-sessions ConcurrentSessionControlAuthenticationStrategy屬性映射到maximumSessions.

  • session-registry-alias 他也能夠是有用的,對內部會話註冊表有一個參考,用於在你本身的beans或管理接口. 使用 session-registry-alias屬性,能夠使內部bean公開, 給它一個名稱,你能夠在你的配置中的其餘地方使用.

  • session-registry-ref 用戶能夠提供本身的` sessionregistry 實現使用`session-registry-ref 屬性. 其餘併發會話控制beans將被鏈接起來使用它.

<x509>

增長了支持X.509認證. 一個 X509AuthenticationFilter 將被添加到堆棧和 Http403ForbiddenEntryPoint bean 被建立. 後者只會在沒有其餘認證機制的時候使用(它惟一的功能是返回一個HTTP 403錯誤代碼). ` preauthenticatedauthenticationprovider`也將建立一個將用戶權限加載到一個` userdetailsservice `的地方中.

<x509>父元素
<x509> 屬性
  • authentication-details-source-ref 引用一個 AuthenticationDetailsSource

  • subject-principal-regex 定義一個正則表達式,該表達式將用於從證書中提取用戶名 (用於使用 UserDetailsService).

  • user-service-ref 容許使用特定的 `UserDetailsService`X.509的狀況下配置多個實例.若是沒有設置,將試圖自動找到一個合適的實例,並使用.

<filter-chain-map>

用於顯式配置filterchainproxy與filterchainmap實例

<filter-chain-map> 屬性
  • request-matcher 定義策略用於匹配傳入請求的使用. 目前的選項是'ant'(螞蟻路徑模式), 'regex'正則表達式和'ciRegex' 不區分大小寫的正則表達式.

<filter-chain-map>子元素

<filter-chain>

用於定義一個特定的URL模式和適用於該模式匹配的URL的過濾器列表.當多個filter-chain元素組合在一個列表中爲了配置FilterChainProxy,最具體的模式必須放在列表的頂部,在底部最通常的模式.

<filter-chain>父元素
<filter-chain> 屬性
  • filters 一個逗號分隔的列表引用Spring bean實現 Filter. 值"none"意味着沒有 Filter應該用於` FilterChain `.

  • request-matcher-ref 引用一個` requestmatcher 將用於肯定是否有一些`Filter來自 filters應該被調用的屬性.

<filter-security-metadata-source>

用於顯式配置FilterSecurityMetadataSource FilterSecurityInterceptor bean使用. 若是你正在配置FilterChainProxy,只須要明確的這一個,而不是使用<http>元素.截取只包含方法和訪問屬性模式的intercept-url.任何其餘的將致使配置錯誤.

<filter-security-metadata-source> 屬性
  • id 一個bean標識符, 用於指在上下文中的其餘地方的bean.

  • lowercase-comparisons 比較後迫使小寫

  • request-matcher 定義用於匹配傳入請求的策略.目前的選擇是 'ant'(螞蟻路徑模式), 'regex' 正則表達式和'ciRegex' 不區分大小寫的正則表達式.

  • use-expressions 能夠使用在<intercept-url>元素中表達式'access'的屬性,而不是傳統的配置屬性的列表.默認爲 'true'.若是啓用,每一個屬性應該包含一個單一的布爾表達式. 若是表達式計算結果爲'true',則訪問將被授予.

<filter-security-metadata-source>子元素

WebSocket 安全

Spring Security 4.0+爲受權消息提供支持.這是一個爲WebSocket基礎應用程序提供受權有用的例子.

<websocket-message-broker>

websocket-message-broker元素有兩種不一樣的模式. 若是websocket-message-broker@id 沒有指定,那麼它會作如下事情:

  • 確保任何SimpAnnotationMethodMessageHandler AuthenticationPrincipalArgumentResolver註冊做爲一個自定義參數解析器. 這容許使用 @AuthenticationPrincipal 來解決當前的主要Authentication

  • 確保securitycontextchannelinterceptor自動註冊爲clientinboundchannel. 這與用戶填充SecurityContextHolder消息中被發現.

  • 確保channelsecurityinterceptor與clientinboundchannel註冊. 這容許受權規則指定的消息.

  • 確保CsrfChannelInterceptor與clientInboundChannel註冊.這將確保只有從原來的域的請求被啓用. *確保CsrfTokenHandshakeInterceptor與WebSocketHttpRequestHandler, TransportHandlingSockJsService,或DefaultSockJsService註冊.這保證了預期的csrftoken來自消息複製到WebSocket Session屬性.

若是額外的控制是必要的,能夠指定ID和channelsecurityinterceptor將分配給指定的ID. 全部的佈線與Spring的消息傳遞基礎設施能夠手動完成的.這是比較麻煩的,但提供了更大的配置控制.

<websocket-message-broker>屬性
  • id 一個bean的標識符,用於指在channelsecurityinterceptor bean的上下文中的任何地方. 若是指定,Spring Security須要在Spring Messaging內明確的配置. 若是沒有指定,Spring Security會自動整合與通信基礎設施,如<websocket-message-broker>描述的.

  • same-origin-disabled 禁用要求CSRF令牌出如今Stomp headers(默認錯誤). 若是有必要讓其餘起源SockJS鏈接,更改默認是有用的.

<websocket-message-broker>子元素

<intercept-message>

定義消息的受權規則.

<intercept-message>父元素
<intercept-message> 屬性
  • pattern 一種目的基於匹配Message的蟻羣模式.例如, "/" matches any Message with a destination; "/admin/" 匹配任何有一個以"/admin/**"開頭爲目的地的Message".

  • type 要匹配的消息的類型. 在simpmessagetype有效值的定義 (i.e. CONNECT, CONNECT_ACK, HEARTBEAT, MESSAGE, SUBSCRIBE, UNSUBSCRIBE, DISCONNECT, DISCONNECT_ACK, OTHER).

  • access 用於保護信息的表達式.例如,"DenyAll"將拒絕訪問全部的匹配信息;"permitall"將授予訪問全部的匹配信息;"hasrole('admin')"須要當前用戶擁有的角色"role_admin"匹配的信息.

認證服務

在Spring Security 3.0以前, AuthenticationManager 在內部是自動註冊的. 如今,你必須使用 <authentication-manager> 元素明確的註冊一個. 這將建立Spring Security的 ProviderManager類的一個實例, 須要配置一個或多個` AuthenticationProvider 實例. 這些均可以使用命名空間提供的語法元素來建立, 也能夠是標準的bean定義, 標記爲除了使用 `authentication-provider元素的列表.

<authentication-manager>

每一個Spring Security應用程序使用名稱空間必須包括這個元素.它負責註冊的` authenticationManager 爲應用提供認證服務. 全部元素的建立 AuthenticationProvider `實例應該是這個子元素.

<authentication-manager> 屬性
  • alias 此屬性容許你爲你本身的配置中使用的內部實例定義別名. 它的用途是描述在namespace introduction.

  • erase-credentials 若是設置爲真, AuthenticationManager將試圖清除任何憑據數據在返回的驗證對象中, 一旦用戶已被身份驗證.實際上它映射到eraseCredentialsAfterAuthentication屬性的 ProviderManager. 這是在 Core Services 章節中討論的.

  • id 此屬性容許你爲內部實例定義一個用於在本身的配置中使用的標識. 它是相同的別名元素, 但提供了一個更加一致的經驗使用id屬性的元素.

<authentication-manager>子元素

<authentication-provider>

除非用` REF 屬性, 這個元素是縮寫配置一個 DaoAuthenticationProvider. `DaoAuthenticationProvider 加載用戶信息從一個` userdetailsservice 和用戶名/密碼組合所提供的登陸時比較. ` userdetailsservice `實例能夠經過使用可用的命名空間元素定義 ( `jdbc-user-service 或者經過使用 user-service-ref 屬性指向一個bean定義在應用程序上下文). 在 namespace introduction中你能夠找到這些變化的例子.

<authentication-provider>父元素
<authentication-provider> 屬性
  • ref 定義引用一個Spring bean實現AuthenticationProvider.

若是你寫了本身的 AuthenticationProvider實現(或者想配置一個Spring Security的實現做爲一個傳統的bean,而後,你能夠使用下面的語法將它添加到` providermanager ` 內部列表:

<security:authentication-manager>
<security:authentication-provider ref="myAuthenticationProvider" />
</security:authentication-manager>
<bean id="myAuthenticationProvider" class="com.something.MyAuthenticationProvider"/>
  • user-service-ref 引用bean實現UserDetailsService能夠建立使用標準的bean元素或自定義 ser-service 元素.

<jdbc-user-service>

建立一個JDBC-based UserDetailsService.

<jdbc-user-service> 屬性
  • authorities-by-username-query 一個SQL語句查詢用戶授予政府給定的用戶名.

默認爲

select username, authority from authorities where username = ?
  • cache-ref 定義引用UserDetailsService緩存.

  • data-source-ref bean ID 提供所需的表的數據源.

  • group-authorities-by-username-query 一條SQL語句來查詢用戶組部門給定的用戶名.

默認爲

+

select
g.id, g.group_name, ga.authority
from
groups g, group_members gm, group_authorities ga
where
gm.username = ? and g.id = ga.group_id and g.id = gm.group_id
  • id bean標識符, 用於bean在上下文的任何地方.

  • role-prefix 從永久存儲(默認是 "ROLE_")中,一個非空字符串前綴字符串將被添加到角色加載.在默認爲非空的狀況下,使用沒有前綴的值"none".

  • users-by-username-query 一個SQL語句查詢用戶名、密碼,並啓用了一個用戶名狀態. 默認爲

    select username, password, enabled from users where username = ?

<password-encoder>

namespace introduction所描述的,身份驗證提供者能夠被配置爲使用一個密碼編碼器. 這將致使bean注入到相應的` passwordencoder 實例中, 可能可能伴隨 `SaltSource bean提供鹽散列值.

<password-encoder>父元素
<password-encoder>屬性
  • base64 一個字符串是否應該被Base64編碼

  • hash 定義用於用戶密碼的散列算法.咱們強烈建議你不要使用MD4,由於它是一個很是弱的散列算法.

  • ref 定義引用一個Spring bean 實現PasswordEncoder.

<password-encoder>子元素

<salt-source>

口令保護策略. 能夠使用來自UserDetails對象的系統常數和屬性.

<salt-source>父元素
<salt-source>屬性
  • ref 定義引用一個Spring bean Id.

  • system-wide 一個單一的值,將被用來做爲一個密碼編碼器的salt.

  • user-property UserDetails對象的屬性將被用做salt經過密碼編碼器. 一般狀況下,像"username"可能會被使用.

<user-service>

從屬性文件或列表中的"user"子元素建立一個UserDetailsService內存. 內部轉換爲小寫,容許用戶名不區分大小寫的查詢,因此這個不該使用是否須要區分大小寫.

<user-service> 屬性
  • id bean標識符,用於指bean在上下文的任何地方.

  • properties 其中屬性文件的位置,每一行的格式爲

    username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
<user-service>子元素

<user>

表示應用程序中的用戶.

<user>父元素
<user> 屬性
  • authorities 一個或多個authorities授予的用戶. 用逗號隔開authorities (但沒有空間).例如, "ROLE_USER,ROLE_ADMINISTRATOR"

  • disabled 能夠設置爲"true"來標記一個賬戶禁用,沒法使用.

  • locked 能夠設置爲"true"來標記一個賬戶鎖定,沒法使用.

  • name 分配給用戶的用戶名.

  • password 分配給用戶的密碼. 若是相應的認證供應商支持哈希(記得設置"user-service"的 "hash"屬性元素),這多是散列.此屬性被省略的狀況下,該數據將不會被用於身份驗證.但僅用於訪問authorities.若是省略,命名空間將生成一個隨機值,防止其意外使用身份驗證。不能爲空.

方法安全性

<global-method-security>

這個元素的主要手段是在Spring Security beans中添加支持安全方法.能夠經過使用註釋擔保(在接口或類定義)或經過定義一組的切入點做爲子元素的方法,使用AspectJ語法.

<global-method-security> 屬性
  • access-decision-manager-ref 使用與AccessDecisionManager相同的安全方法配置網絡安全, 但這能夠使用此屬性覆蓋.默認狀況下AffirmativeBased實現用於RoleVoter和AuthenticatedVoter.

  • authentication-manager-ref 引用一個 AuthenticationManager ,應該用於方法安全性.

  • jsr250-annotations 指定是否使用JSR-250樣式屬性(例如"RolesAllowed"). 這將須要javax.annotation.安全類在類路徑中.將此設置爲真也增長一個 Jsr250VoterAccessDecisionManager,因此你須要確保你這樣作,若是你正在使用一個自定義的實現和想要使用這些註釋.

  • metadata-source-ref 外部methodsecuritymetadatasource實例能夠提供優先於其餘來源(如默認的註釋).

  • mode 該屬性能夠設置爲"AspectJ"指定AspectJ應該用來代替默認的Spring AOP. 方法安全性必須被來自spring-security-aspects組件AnnotationSecurityAspect編排.

須要注意的是AspectJ遵循Java接口上的註釋不是繼承的.這意味着定義接口的Security annotaitons方法將是不安全的. 相反, 當在使用AspectJ時,你必須把Security annotation放在類上.

  • order 容許建議"order"將被設置爲方法安全攔截.

  • pre-post-annotations 指定是否使用Spring Security的先後調用註釋 (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) 應該支持這個應用程序上下文。默認爲"disabled".

  • proxy-target-class 若是這是真的,將使用基於類的代理,而不是基於接口的代理.

  • run-as-manager-ref 引用一個可選的RunAsManager實現可經過配置的MethodSecurityInterceptor

  • secured-annotations 指定是否使用Spring Security的 @Secured annotations 啓用應用程序上下文. 默認爲 "disabled".

相關文章
相關標籤/搜索