zoukankan      html  css  js  c++  java
  • Spring Security OAuth2之resource_id配置与验证

    一、resource_id的作用

    OAuth2认证流程

    Spring Security OAuth2 架构上分为Authorization Server认证服务器和Resource Server资源服务器。我们可以为每一个Resource Server(一个微服务实例)设置一个resourceid。Authorization Server给client第三方客户端授权的时候,可以设置这个client可以访问哪一些Resource Server资源服务,如果没设置,就是对所有的Resource Server都有访问权限。

    二、ResourceServer如何设置ResourceID

    在每个ResourceServer实例上设置resourceId,该resourceId作为该服务资源的唯一标识。(假如同一个微服务资源部署多份,resourceId相同)

    @Configuration
    @EnableResourceServer
    public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {
    
        private static final String DEMO_RESOURCE_ID = "test-resource";
    
        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            resources.resourceId(DEMO_RESOURCE_ID)
            //...... 还可以有有其他的配置
        }
     }
    
    

    三、AuthorizationServer如何设置ResourceIDs

    在AuthorizationServer为客户端client配置ResourceID的目的是:限制某个client可以访问的资源服务。

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //配置客户端存储到db 代替原来得内存模式
        JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
        clientDetailsService.setPasswordEncoder(passwordEncoder);
        clients.withClientDetails(clientDetailsService);
    }
    

    这里需要使用JdbcClientDetailsService类和数据库表oauth_client_details进行配置的持久化存储,以及动态配置。

    oauth_client_details

    三、ResourceID在哪验证

    ResourceID当然是在Resource Server资源服务器进行验证(你能不能访问我的资源,当然由我自己来验证)。当资源请求发送到Resource Server的时候会携带access_token,Resource Server会根据access_token找到client_id,进而找到该client可以访问的resource_ids。如果resource_ids包含ResourceServer自己设置ResourceID,这关就过去了,就可以继续进行其他的权限验证。

    • @EnableResourceServer会给Spring Security的FilterChan添加一个OAuth2AuthenticationProcessingFilter过滤器,过滤所有的资源请求。
    • OAuth2AuthenticationProcessingFilter会使用OAuth2AuthenticationManager来验证token。验证Token的时候会去oauth_client_details表加载client配置信息。

    如果AuthorizationServer认证client1可以访问test-resource,但client1去访问了oauth-rs,会响应如下信息:

    {"error":"access_denied","error_description":"Invalid token does not contain resource id (oauth-rs)"}
    

    具体实现resource_id验证的源码:OAuth2AuthenticationManager#authenticate(Authentication authentication)

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    
            if (authentication == null) {
                throw new InvalidTokenException("Invalid token (token not found)");
            }
            String token = (String) authentication.getPrincipal();
            OAuth2Authentication auth = tokenServices.loadAuthentication(token);
            if (auth == null) {
                throw new InvalidTokenException("Invalid token: " + token);
            }
    
            Collection<String> resourceIds = auth.getOAuth2Request().getResourceIds();
            if (resourceId != null && resourceIds != null && !resourceIds.isEmpty() && !resourceIds.contains(resourceId)) {
                throw new OAuth2AccessDeniedException("Invalid token does not contain resource id (" + resourceId + ")");
            }
    
            checkClientDetails(auth);
    
            if (authentication.getDetails() instanceof OAuth2AuthenticationDetails) {
                OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
                // Guard against a cached copy of the same details
                if (!details.equals(auth.getDetails())) {
                    // Preserve the authentication details from the one loaded by token services
                    details.setDecodedDetails(auth.getDetails());
                }
            }
            auth.setDetails(authentication.getDetails());
            auth.setAuthenticated(true);
            return auth;
    
        }
    

    下面这段便是验证resourceid的地方

    Collection<String> resourceIds = auth.getOAuth2Request().getResourceIds();
    if (resourceId != null && resourceIds != null && !resourceIds.isEmpty() && !resourceIds.contains(resourceId)) {
        throw new OAuth2AccessDeniedException("Invalid token does not contain resource id (" + resourceId + ")");
    }
    

    在Spring Security的FilterChain中,OAuth2AuthenticationProcessingFilter在FilterSecurityInterceptor的前面,所以会先验证client有没有此resource的权限,只有在有此resource的权限的情况下,才会再去做进一步的进行其他验证的判断。

    欢迎关注我的博客,里面有很多精品合集

    • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客

    觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

  • 相关阅读:
    未能创建可接受的游标。
    怎样修改查看Oracle字符集
    2005年国内各大公司的薪酬一览 同学发给我的,留在这里刺激一下自己,不过他说到了中国工程物理研究院(四川绵阳) 对此不表同意,具体情况我可最清楚呀,哈哈
    破解低价笔记本惊人的秘密
    Struts 的安装、配置与运行zt
    有用的数据:30款市场主流车型真实油耗一览
    JDBC连接Oracle数据库常见问题及解决方法
    查锁的方法
    用Oracle闪回功能恢复偶然丢失的数据数据被误删除了,多亏了万能的oracle,....后怕
    powerdesigner中去掉生成sql中的引号
  • 原文地址:https://www.cnblogs.com/zimug/p/13389348.html
Copyright © 2011-2022 走看看