首页 文章

如何在Spring Security中动态指定OAuth2资源详细信息?

提问于
浏览
4

我是_1396906的API,它使用OAuth2进行身份验证和授权 . 使用the tutorial for Spring Security OAuth2the tutorial for Shopify,我已经能够与单个商店进行集成 . YAML配置如下所示:

shopify:
  shop: myshop
  scopes: read_customers,read_orders
security:
  oauth2:
    client:
      clientId: myclientid
      clientSecret: mysecret
      tokenName: access_token
      authenticationScheme: query
      clientAuthenticationScheme: form
      accessTokenUri: https://${shopify.shop}.myshopify.com/admin/oauth/access_token
      userAuthorizationUri: https://${shopify.shop}.myshopify.com/admin/oauth/authorize?scope=${shopify.scopes}&grant_options[]=
      pre-established-redirect-uri: https://myapp/login
      registered-redirect-uri: https://myapp/login
      use-current-uri: false
    resource:
      userInfoUri: https://${shopify.shop}.myshopify.com/admin/shop.json

但是,此静态配置赢得了App Store,因为重定向,访问令牌,用户信息和用户授权URI取决于商店名称 . There are examples of using more than one provider,但它们仍然必须是静态的 .

为了让这些URI成为动态,我想出了一些可能的选择:

  • 使用 /login 路径中的参数来标识商店,然后创建一个过滤器,将商店名称添加到之前运行的 ThreadLocal ,然后通过Spring代理的工厂bean动态创建OAuth2过滤器所需的 AuthorizationCodeResourceDetails .

  • 使用一种"metafilter",它可以动态地为每个请求重新创建 OAuth2ClientAuthenticationProcessingFilter 以及它所需的所有资源 .

  • 覆盖 OAuth2ClientAuthenticationProcessingFilter ,以便它可以处理重新创建它需要获取访问令牌的 RestTemplate .

所有这些选项似乎都很难 . 在Spring Security OAuth2中处理动态生成的URI以获取访问令牌和用户信息的好方法是什么?

此外,由于我一般都是OAuth2的新用户,我是否需要在Spring配置中启用资源服务器以使用访问令牌保护我的应用程序?

2 回答

  • 1

    有点晚了,但我确实通过覆盖Oauth2ProtectedResource的getter来返回oauth资源的动态URL

    @Bean(name = "googleOauthResource")
    public BaseOAuth2ProtectedResourceDetails getGoogleOauthResource() {
        final AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails() {
            @Override
            public String getPreEstablishedRedirectUri() {
                final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
                if (requestAttributes instanceof ServletRequestAttributes) {
                    final HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
                    return request.getRequestURL() + "?" + request.getQueryString() + "&addStuff";
                }
    
                return super.getPreEstablishedRedirectUri();
            }
        };
        details.setId("google-oauth-client");
        details.setClientId("xxxxxxxxxxx");
        details.setClientSecret("xxxxxxxx");
        details.setAccessTokenUri("https://www.googleapis.com/oauth2/v4/token");
        details.setUserAuthorizationUri("https://accounts.google.com/o/oauth2/v2/auth");
        details.setTokenName("authorization_code");
        details.setScope(Arrays.asList("https://mail.google.com/,https://www.googleapis.com/auth/gmail.modify"));
        details.setPreEstablishedRedirectUri("http://localhost:8080/xxx-api-web/v2/gmail"); //TODO
        details.setUseCurrentUri(false);
        details.setAuthenticationScheme(AuthenticationScheme.query);
        details.setClientAuthenticationScheme(AuthenticationScheme.form);
        details.setGrantType("authorization_code");
        return details;
    }
    
  • 1

    我遇到了同样的问题,我倾向于你使用ThreadLocal存储的第一个理论 . 以下是我可能会解决的问题:

    通过覆盖OAuth2ClientAuthenticationProcessingFilter中的方法,在LocalThread存储中设置ServletRequest的值:

    • 尝试验证

    • successAuthentication

    • failedfulfulAuthentication

    • 要求身份验证

    然后通过覆盖followign方法在OAuth2RestTemplate中翻译URI:

    • createRequest

    • doExecute

    • appendQueryParameter

    我可能不得不为RestTemplate创建我自己的@Bean,它有一个注入@Service来查找动态Shopify域 .

    如果有效,我会发布我的解决方案 .

相关问题