spring-security-oauth2_vsftpd配置[通俗易懂]

spring-security-oauth2_vsftpd配置[通俗易懂]1.先看下官方文档的说明地址:https://projects.spring.io/spring-security-oauth/docs/oauth2.htmlscope:Thescopetowhichtheclie

1.先看下官方文档的说明
  • 地址:https://projects.spring.io/spring-security-oauth/docs/oauth2.html
  • scope: The scope to which the client is limited. If scope is undefined or empty (the default) the client is not limited by scope.
  • 用来限制客户端的访问范围,如果为空(默认)的话,那么客户端拥有全部的访问范围
    scope中文翻译就是作用域,用来限制客户端权限访问的范围,可以用来设置角色或者权限,也可以不设置。

虽然官方网站说是服务器端的client配置scopes可以为空,但是经过实际操作及跟踪源码来看password模式下调用/oauth/token端点拿用户token信息服务端可以为空,
但是客户端必须传scopes;refresh_token模式服务端及client端的scopes都 需要配置,所以即使我们用不到scopes前后端最好都配置上scopes(“all”);

资料信息:https://stackoverflow.com/questions/39756748/spring-oauth-authorization-server-requires-scope

2.scopes的校验是在TokenEndpoint进行的
   @RequestMapping(
        value = {"/oauth/token"},
        method = {RequestMethod.POST}
    )
    public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
        if (!(principal instanceof Authentication)) {
            throw new InsufficientAuthenticationException("There is no client authentication. Try adding an appropriate authentication filter.");
        } else {
            String clientId = this.getClientId(principal);
            ClientDetails authenticatedClient = this.getClientDetailsService().loadClientByClientId(clientId);
            //OAuth2RequestFactory接口的实现类DefaultOAuth2RequestFactory创建token请求对象
            TokenRequest tokenRequest = this.getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);
            if (clientId != null && !clientId.equals("") && !clientId.equals(tokenRequest.getClientId())) {
                throw new InvalidClientException("Given client ID does not match authenticated client");
            } else {
                //校验scope客户端和服务器端的设置是否匹配
                if (authenticatedClient != null) {
                    this.oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
                }

                if (!StringUtils.hasText(tokenRequest.getGrantType())) {
                    throw new InvalidRequestException("Missing grant type");
                } else if (tokenRequest.getGrantType().equals("implicit")) {
                    throw new InvalidGrantException("Implicit grant type not supported from token endpoint");
                } else {
                    if (this.isAuthCodeRequest(parameters) && !tokenRequest.getScope().isEmpty()) {
                        this.logger.debug("Clearing scope of incoming token request");
                        tokenRequest.setScope(Collections.emptySet());
                    }

                    if (this.isRefreshTokenRequest(parameters)) {
                        tokenRequest.setScope(OAuth2Utils.parseParameterList((String)parameters.get("scope")));
                    }

                    OAuth2AccessToken token = this.getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
                    if (token == null) {
                        throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
                    } else {
                        return this.getResponse(token);
                    }
                }
            }
        }
    }
3.进入this.oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);查看处理逻辑

oAuth2RequestValidator对象是DefaultOAuth2RequestValidator的实例,进入看下实现逻辑:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

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

import java.util.Iterator;
import java.util.Set;
import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.OAuth2RequestValidator;
import org.springframework.security.oauth2.provider.TokenRequest;

public class DefaultOAuth2RequestValidator implements OAuth2RequestValidator {
    public DefaultOAuth2RequestValidator() {
    }

    public void validateScope(AuthorizationRequest authorizationRequest, ClientDetails client) throws InvalidScopeException {
        this.validateScope(authorizationRequest.getScope(), client.getScope());
    }
    //校验客户端scope和服务端sope方法
    public void validateScope(TokenRequest tokenRequest, ClientDetails client) throws InvalidScopeException {
        this.validateScope(tokenRequest.getScope(), client.getScope());
    }
    //实际的校验方法
    private void validateScope(Set<String> requestScopes, Set<String> clientScopes) {
        //客户端scope不为空并且scope在服务端scope限制范围之内通过校验
        //客户端scope不为空,服务端为空或不设置通过校验
        if (clientScopes != null && !clientScopes.isEmpty()) {
            Iterator var3 = requestScopes.iterator();

            while(var3.hasNext()) {
                String scope = (String)var3.next();
                if (!clientScopes.contains(scope)) {
                    throw new InvalidScopeException("Invalid scope: " + scope, clientScopes);
                }
            }
        }
        //如果客户端的scope为空将会抛出异常,所以客户端不可以为空
        if (requestScopes.isEmpty()) {
            throw new InvalidScopeException("Empty scope (either the client or the user is not allowed the requested scopes)");
        }
    }
}
4.DefaultOAuth2RequestFactory实现类组装token请求及校验scopes
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

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

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.DefaultSecurityContextAccessor;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
import org.springframework.security.oauth2.provider.SecurityContextAccessor;
import org.springframework.security.oauth2.provider.TokenRequest;

public class DefaultOAuth2RequestFactory implements OAuth2RequestFactory {
    private final ClientDetailsService clientDetailsService;
    private SecurityContextAccessor securityContextAccessor = new DefaultSecurityContextAccessor();
    private boolean checkUserScopes = false;

    public DefaultOAuth2RequestFactory(ClientDetailsService clientDetailsService) {
        this.clientDetailsService = clientDetailsService;
    }

    public void setSecurityContextAccessor(SecurityContextAccessor securityContextAccessor) {
        this.securityContextAccessor = securityContextAccessor;
    }

    public void setCheckUserScopes(boolean checkUserScopes) {
        this.checkUserScopes = checkUserScopes;
    }

    public AuthorizationRequest createAuthorizationRequest(Map<String, String> authorizationParameters) {
        String clientId = (String)authorizationParameters.get("client_id");
        String state = (String)authorizationParameters.get("state");
        String redirectUri = (String)authorizationParameters.get("redirect_uri");
        Set<String> responseTypes = OAuth2Utils.parseParameterList((String)authorizationParameters.get("response_type"));
        Set<String> scopes = this.extractScopes(authorizationParameters, clientId);
        AuthorizationRequest request = new AuthorizationRequest(authorizationParameters, Collections.emptyMap(), clientId, scopes, (Set)null, (Collection)null, false, state, redirectUri, responseTypes);
        ClientDetails clientDetails = this.clientDetailsService.loadClientByClientId(clientId);
        request.setResourceIdsAndAuthoritiesFromClientDetails(clientDetails);
        return request;
    }

    public OAuth2Request createOAuth2Request(AuthorizationRequest request) {
        return request.createOAuth2Request();
    }
    //创建请求入口类
    public TokenRequest createTokenRequest(Map<String, String> requestParameters, ClientDetails authenticatedClient) {
        String clientId = (String)requestParameters.get("client_id");
        if (clientId == null) {
            clientId = authenticatedClient.getClientId();
        } else if (!clientId.equals(authenticatedClient.getClientId())) {
            throw new InvalidClientException("Given client ID does not match authenticated client");
        }

        String grantType = (String)requestParameters.get("grant_type");
        //获取客户端传递或者服务端的scope
        Set<String> scopes = this.extractScopes(requestParameters, clientId);
        TokenRequest tokenRequest = new TokenRequest(requestParameters, clientId, scopes, grantType);
        return tokenRequest;
    }

    public TokenRequest createTokenRequest(AuthorizationRequest authorizationRequest, String grantType) {
        TokenRequest tokenRequest = new TokenRequest(authorizationRequest.getRequestParameters(), authorizationRequest.getClientId(), authorizationRequest.getScope(), grantType);
        return tokenRequest;
    }

    public OAuth2Request createOAuth2Request(ClientDetails client, TokenRequest tokenRequest) {
        return tokenRequest.createOAuth2Request(client);
    }
    //如果参数中的scope为null,则从服务端配置的scope中取,并且根据this.checkUserScopes的值判断是否校验scopes的有效性
    private Set<String> extractScopes(Map<String, String> requestParameters, String clientId) {
        Set<String> scopes = OAuth2Utils.parseParameterList((String)requestParameters.get("scope"));
        ClientDetails clientDetails = this.clientDetailsService.loadClientByClientId(clientId);
        if (scopes == null || scopes.isEmpty()) {
            scopes = clientDetails.getScope();
        }

        if (this.checkUserScopes) {
            scopes = this.checkUserScopes(scopes, clientDetails);
        }

        return scopes;
    }

    private Set<String> checkUserScopes(Set<String> scopes, ClientDetails clientDetails) {
        if (!this.securityContextAccessor.isUser()) {
            return scopes;
        } else {
            Set<String> result = new LinkedHashSet();
            Set<String> authorities = AuthorityUtils.authorityListToSet(this.securityContextAccessor.getAuthorities());
            Iterator var5 = scopes.iterator();

            while(true) {
                String scope;
                do {
                    if (!var5.hasNext()) {
                        return result;
                    }

                    scope = (String)var5.next();
                } while(!authorities.contains(scope) && !authorities.contains(scope.toUpperCase()) && !authorities.contains("ROLE_" + scope.toUpperCase()));

                result.add(scope);
            }
        }
    }
}

GitHub源码:https://github.com/mingyang66/spring-parent/tree/master/spring-security-oauth2-server-redis-service

今天的文章spring-security-oauth2_vsftpd配置[通俗易懂]分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/87364.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注