Spring Security Web 5.1.2 原始碼解析 -- DefaultWebSecurityExpressionHandler 預設Web安全表示式處理器
阿新 • • 發佈:2018-12-12
概述
DefaultWebSecurityExpressionHandler
是Spring Security Web
用於Web
安全表示式處理器(handler
)。它會基於一組預設配置,和當時的環境,對指定的Web
安全表示式求值。
DefaultWebSecurityExpressionHandler
對給定的認證token
和請求上下文FilterInvocation
建立一個評估上下文EvaluationContext
。然後供SPEL
求值使用。比如在WebExpressionVoter
中它被這麼應用 :
public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation> {
// expressionHandler 預設使用 DefaultWebSecurityExpressionHandler
private SecurityExpressionHandler<FilterInvocation> expressionHandler =
new DefaultWebSecurityExpressionHandler();
public int vote(Authentication authentication, FilterInvocation fi,
Collection<ConfigAttribute> attributes) {
assert authentication != null;
assert fi != null;
assert attributes != null;
// 獲取Web安全表示式配置屬性
WebExpressionConfigAttribute weca = findConfigAttribute(attributes);
if (weca == null) {
// 如果沒有相應配置,返回 ACCESS_ABSTAIN:0 表示棄權
return ACCESS_ABSTAIN;
}
// 預設使用 DefaultWebSecurityExpressionHandler 建立 EvaluationContext
EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication,
fi);
ctx = weca.postProcess(ctx, fi);
// 獲取Web安全表示式配置屬性weca中的表示式,和上面所建立的表示式求值上下文ctx,
// 對其進行求值,結果按 boolean 型別處理
// 如果求值結果為 true, 返回 ACCESS_GRANTED:1, 否則返回 ACCESS_DENIED:-1
return ExpressionUtils.evaluateAsBoolean(weca.getAuthorizeExpression(), ctx) ? ACCESS_GRANTED
: ACCESS_DENIED;
}
原始碼解析
package org.springframework.security.web.access.expression;
import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.access.expression.SecurityExpressionOperations;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
import org.springframework.util.Assert;
public class DefaultWebSecurityExpressionHandler extends
AbstractSecurityExpressionHandler<FilterInvocation> implements
SecurityExpressionHandler<FilterInvocation> {
// 用於識別一個Authentication物件是否 anonymous, rememberMe
// 預設使用AuthenticationTrustResolverImpl
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
// 預設使用的角色字首
private String defaultRolePrefix = "ROLE_";
// 對給定的認證token authentication 和給定的請求上下文 fi 構建 SecurityExpressionOperations,
// 此 SecurityExpressionOperations 用於進一步構建 EvaluationContext 物件
@Override
protected SecurityExpressionOperations createSecurityExpressionRoot(
Authentication authentication, FilterInvocation fi) {
WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(trustResolver);
root.setRoleHierarchy(getRoleHierarchy());
root.setDefaultRolePrefix(this.defaultRolePrefix);
return root;
}
/**
* Sets the AuthenticationTrustResolver to be used. The default is
* AuthenticationTrustResolverImpl.
*
* @param trustResolver the AuthenticationTrustResolver to use. Cannot be
* null.
*/
public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
Assert.notNull(trustResolver, "trustResolver cannot be null");
this.trustResolver = trustResolver;
}
/**
*
* Sets the default prefix to be added to
* org.springframework.security.access.expression.SecurityExpressionRoot#hasAnyRole(String...)
* or org.springframework.security.access.expression.SecurityExpressionRoot#hasRole(String).
* For example, if hasRole("ADMIN") or hasRole("ROLE_ADMIN")
* is passed in, then the role ROLE_ADMIN will be used when the defaultRolePrefix is
* "ROLE_" (default).
*
* 設定表示式hasAnyRole(String...)或者hasRole(String)使用的角色字首。不呼叫該方法,則使用預設值
* "ROLE_"。
*
* If null or empty, then no default role prefix is used.
* 如果呼叫了該方法,設定引數為 null 或者 "", 表明不使用角色字首。
*
* @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_".
*/
public void setDefaultRolePrefix(String defaultRolePrefix) {
this.defaultRolePrefix = defaultRolePrefix;
}
}
DefaultWebSecurityExpressionHandler
繼承自AbstractSecurityExpressionHandler
,真正建立EvaluationContext
的方法也是現在該類中:
package org.springframework.security.access.expression;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;
/**
* Base implementation of the facade which isolates Spring Security's requirements for
* evaluating security expressions from the implementation of the underlying expression
* objects.
* Spring Security安全表示式求值實現的通用邏輯基類,同具體某種底層安全表示式實現,比如Web安全,隔離開來。
*
* @author Luke Taylor
* @since 3.1
*/
public abstract class AbstractSecurityExpressionHandler<T> implements
SecurityExpressionHandler<T>, ApplicationContextAware {
// 預設使用 spel parser
private ExpressionParser expressionParser = new SpelExpressionParser();
private BeanResolver br;
private RoleHierarchy roleHierarchy;
// 預設使用 denyAll 評估器
private PermissionEvaluator permissionEvaluator = new DenyAllPermissionEvaluator();
public final ExpressionParser getExpressionParser() {
return expressionParser;
}
public final void setExpressionParser(ExpressionParser expressionParser) {
Assert.notNull(expressionParser, "expressionParser cannot be null");
this.expressionParser = expressionParser;
}
/**
* Invokes the internal template methods to create StandardEvaluationContext
* and SecurityExpressionRoot objects.
*
* @param authentication the current authentication object
* @param invocation the invocation (filter, method, channel)
* @return the context object for use in evaluating the expression, populated with a
* suitable root object.
*/
public final EvaluationContext createEvaluationContext(Authentication authentication,
T invocation) {
// createEvaluationContext 由子類提供具體實現,根據自己所服務的安全環境建立相應的
// SecurityExpressionOperations 物件
SecurityExpressionOperations root = createSecurityExpressionRoot(authentication,
invocation);
// 建立 EvaluationContext, 實現類使用標準實現 StandardEvaluationContext
StandardEvaluationContext ctx = createEvaluationContextInternal(authentication,
invocation);
// 表示式求值可能需要用到bean,這裡指定bean解析器,通常指向整個Spring bean容器
ctx.setBeanResolver(br);
// 設定 EvaluationContext 的根物件為上面建立的 SecurityExpressionOperations root
ctx.setRootObject(root);
return ctx;
}
/**
* Override to create a custom instance of StandardEvaluationContext.
* 一個StandardEvaluationContext或者其子類,
* 預設是一個StandardEvaluationContext , 子類可以覆蓋該方法提供一個自定義的
* StandardEvaluationContext子類例項
*
* The returned object will have a SecurityExpressionRootPropertyAccessor
* added, allowing beans in the ApplicationContext to be accessed via
* expression properties.
*
* @param authentication the current authentication object
* @param invocation the invocation (filter, method, channel)
* @return A StandardEvaluationContext or potentially a custom subclass if
* overridden.
*/
protected StandardEvaluationContext createEvaluationContextInternal(
Authentication authentication, T invocation) {
return new StandardEvaluationContext();
}
/**
* Implement in order to create a root object of the correct type for the supported
* invocation type.
*
* @param authentication the current authentication object
* @param invocation the invocation (filter, method, channel)
* @return the object wh
*/
protected abstract SecurityExpressionOperations createSecurityExpressionRoot(
Authentication authentication, T invocation);
protected RoleHierarchy getRoleHierarchy() {
return roleHierarchy;
}
public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
this.roleHierarchy = roleHierarchy;
}
protected PermissionEvaluator getPermissionEvaluator() {
return permissionEvaluator;
}
public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
this.permissionEvaluator = permissionEvaluator;
}
public void setApplicationContext(ApplicationContext applicationContext) {
br = new BeanFactoryResolver(applicationContext);
}
}