1. 程式人生 > >Spring Security Web 5.1.2 原始碼解析 -- DefaultWebSecurityExpressionHandler 預設Web安全表示式處理器

Spring Security Web 5.1.2 原始碼解析 -- DefaultWebSecurityExpressionHandler 預設Web安全表示式處理器

概述

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