Spring Security Web 5.1.2 源码解析 -- DefaultWebSecurityExpressionHandler 缺省Web安全表达式处理器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/84941681

概述

DefaultWebSecurityExpressionHandlerSpring 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);
	}
}

猜你喜欢

转载自blog.csdn.net/andy_zhang2007/article/details/84941681