基于Scope的@PreAuthorize 配置计算机(服务)访问权限

JHipster_UAA 配置计算机(服务)访问权限


 
        我们常常配置spring-security-oauth2,用来实现外部应用程序,可以使用我们的应用程序进行身份验证。但是在实际应用中,基于外部应用程序,客户端只能访问一部分用户允许的API.可用子集由OAuth Scopes确定.
 
        Spring OAuth附带了OAuth2MethodSecurityExpressionHandler,该类增加了使用@PreAuthorize表达式进行此类检查的功能.首先需要注册 OAuth2MethodSecurityExpressionHandler。
 


import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;

/**
 * @ClassName: MethodSecurityConfig
 * @Description:
 * @author: 
 * @Date:2020/5/11 
 **/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    
    

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
    
    
        return new OAuth2MethodSecurityExpressionHandler();
    }

}

 
使用 @PreAuthorize 的 hasScope 或 @PreAuthorize 的 hasAnyScope


    @RequestMapping("/ResourceClientApiA")
    @ResponseBody
    //添加机构编码权限,判断该机构是否有权限调用
    @PreAuthorize(value = "#oauth2.hasScope('servera')")
    public String testApiA() {
    
    
        log.info("== 执行 ResourceClientApiA 方法 ==");
        return "Hi,this is ResourceClientApiA !!!";
    }
    
    @RequestMapping("/ResourceClientApiB")
    @ResponseBody
    //添加机构编码权限,判断该机构是否有权限调用
    @PreAuthorize(value = "#oauth2.hasAnyScope('servera','serverb','serverc')")
    public String testApiB() {
    
    
        log.info("== 执行 ResourceClientApiB 方法 ==");
        return "Hi,this is ResourceClientApiB !!!";
    }
    

 
扩展知识:

可以查看OAuth2SecurityExpressionMethods类,该类中有除了hasScope外的其他相关可用方法。

/*
 * Copyright 2006-2011 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package org.springframework.security.oauth2.provider.expression;

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException;

/**
 * A convenience object for security expressions in OAuth2 protected resources, providing public methods that act on the
 * current authentication.
 *
 * <p>
 * @deprecated See the <a href="https://github.com/spring-projects/spring-security/wiki/OAuth-2.0-Migration-Guide">OAuth 2.0 Migration Guide</a> for Spring Security 5.
 *
 * @author Dave Syer
 * @author Rob Winch
 * @author Radek Ostrowski
 * 
 */
@Deprecated
public class OAuth2SecurityExpressionMethods {
    
    

	private final Authentication authentication;

	private Set<String> missingScopes = new LinkedHashSet<String>();

	public OAuth2SecurityExpressionMethods(Authentication authentication) {
    
    
		this.authentication = authentication;
	}

	/**
	 * Check if any scope decisions have been denied in the current context and throw an exception if so. This method
	 * automatically wraps any expressions when using {@link OAuth2MethodSecurityExpressionHandler} or
	 * {@link OAuth2WebSecurityExpressionHandler}.
	 * 
	 * OAuth2Example usage:
	 * 
	 * <pre>
	 * access = &quot;#oauth2.hasScope('read') or (#oauth2.hasScope('other') and hasRole('ROLE_USER'))&quot;
	 * </pre>
	 * 
	 * Will automatically be wrapped to ensure that explicit errors are propagated rather than a generic error when
	 * returning false:
	 * 
	 * <pre>
	 * access = &quot;#oauth2.throwOnError(#oauth2.hasScope('read') or (#oauth2.hasScope('other') and hasRole('ROLE_USER'))&quot;
	 * </pre>
	 * 
	 * N.B. normally this method will be automatically wrapped around all your access expressions. You could use it
	 * explicitly to get more control, or if you have registered your own <code>ExpressionParser</code> you might need
	 * it.
	 * 
	 * @param decision the existing access decision
	 * @return true if the OAuth2 token has one of these scopes
	 * @throws InsufficientScopeException if the scope is invalid and we the flag is set to throw the exception
	 */
	public boolean throwOnError(boolean decision) {
    
    
		if (!decision && !missingScopes.isEmpty()) {
    
    
			Throwable failure = new InsufficientScopeException("Insufficient scope for this resource", missingScopes);
			throw new AccessDeniedException(failure.getMessage(), failure);
		}
		return decision;
	}

	/**
	 * Check if the OAuth2 client (not the user) has the role specified. To check the user's roles see
	 * {@link #clientHasRole(String)}.
	 * 
	 * @param role the role to check
	 * @return true if the OAuth2 client has this role
	 */
	public boolean clientHasRole(String role) {
    
    
		return clientHasAnyRole(role);
	}

	/**
	 * Check if the OAuth2 client (not the user) has one of the roles specified. To check the user's roles see
	 * {@link #clientHasAnyRole(String...)}.
	 * 
	 * @param roles the roles to check
	 * @return true if the OAuth2 client has one of these roles
	 */
	public boolean clientHasAnyRole(String... roles) {
    
    
		return OAuth2ExpressionUtils.clientHasAnyRole(authentication, roles);
	}

	/**
	 * Check if the current OAuth2 authentication has the scope specified.
	 * 
	 * @param scope the scope to check
	 * @return true if the OAuth2 authentication has the required scope
	 */
	public boolean hasScope(String scope) {
    
    
		return hasAnyScope(scope);
	}

	/**
	 * Check if the current OAuth2 authentication has one of the scopes specified.
	 * 
	 * @param scopes the scopes to check
	 * @return true if the OAuth2 token has one of these scopes
	 * @throws AccessDeniedException if the scope is invalid and we the flag is set to throw the exception
	 */
	public boolean hasAnyScope(String... scopes) {
    
    
		boolean result = OAuth2ExpressionUtils.hasAnyScope(authentication, scopes);
		if (!result) {
    
    
			missingScopes.addAll(Arrays.asList(scopes));
		}
		return result;
	}

	/**
	 * Check if the current OAuth2 authentication has one of the scopes matching a specified regex expression.
	 * 
	 * <pre>
	 * access = &quot;#oauth2.hasScopeMatching('.*_admin:manage_scopes')))&quot;
	 * </pre>
	 * 
	 * @param scopeRegex the scope regex to match
	 * @return true if the OAuth2 authentication has the required scope
	 */
	public boolean hasScopeMatching(String scopeRegex) {
    
    
		return hasAnyScopeMatching(scopeRegex);
	}

	/**
	 * Check if the current OAuth2 authentication has one of the scopes matching a specified regex expression.
	 * 
	 * <pre>
	 * access = &quot;#oauth2.hasAnyScopeMatching('admin:manage_scopes','.*_admin:manage_scopes','.*_admin:read_scopes')))&quot;
	 * </pre>
	 * 
	 * @param scopesRegex the scopes regex to match
	 * @return true if the OAuth2 token has one of these scopes
	 * @throws AccessDeniedException if the scope is invalid and we the flag is set to throw the exception
	 */
	public boolean hasAnyScopeMatching(String... scopesRegex) {
    
    

		boolean result = OAuth2ExpressionUtils.hasAnyScopeMatching(authentication, scopesRegex);
		if (!result) {
    
    
			missingScopes.addAll(Arrays.asList(scopesRegex));
		}
		return result;
	}

	/**
	 * Deny access to oauth requests, so used for example to only allow web UI users to access a resource.
	 * 
	 * @return true if the current authentication is not an OAuth2 type
	 */
	public boolean denyOAuthClient() {
    
    
		return !OAuth2ExpressionUtils.isOAuth(authentication);
	}

	/**
	 * Permit access to oauth requests, so used for example to only allow machine clients to access a resource.
	 * 
	 * @return true if the current authentication is not an OAuth2 type
	 */
	public boolean isOAuth() {
    
    
		return OAuth2ExpressionUtils.isOAuth(authentication);
	}

	/**
	 * Check if the current authentication is acting on behalf of an authenticated user.
	 * 
	 * @return true if the current authentication represents a user
	 */
	public boolean isUser() {
    
    
		return OAuth2ExpressionUtils.isOAuthUserAuth(authentication);
	}

	/**
	 * Check if the current authentication is acting as an authenticated client application not on behalf of a user.
	 * 
	 * @return true if the current authentication represents a client application
	 */
	public boolean isClient() {
    
    
		return OAuth2ExpressionUtils.isOAuthClientAuth(authentication);
	}
}

 
       缺点是OAuth2MethodSecurityExpressionHandler扩展了DefaultMethodSecurityExpressionHandler,因此您无法将其与也扩展此类的其他类组合.

 
本文参考 : 如何使用基于Scope的@PreAuthorize保护spring-security-oauth资源?

猜你喜欢

转载自blog.csdn.net/weixin_41922349/article/details/106056509