概述
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;
}
源代码解析
源代码版本 : 5.1.2.RELEASE
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);
}
}