同时为多个社交网络启用OAuth2Sso

Posted

技术标签:

【中文标题】同时为多个社交网络启用OAuth2Sso【英文标题】:EnableOAuth2Sso simultaneously for multiple social networks 【发布时间】:2016-02-04 09:20:53 【问题描述】:

我正在实现一个 Spring Boot 应用程序,该应用程序需要提供 OAuth2 令牌授权并支持多种社交服务(google+、facebook 等)。用户应该能够选择他喜欢的社交网络并使用 OAuth2 授权框架登录。 我正在使用此处描述的方法http://cloud.spring.io/spring-cloud-security/ 实现上述内容。

目前我的 application.yml 看起来像这样

spring:
  oauth2:
    client:
      clientId: my app's google id
      clientSecret: my app's google secret code 
  etc...

另外,spring boot 主类被注解为@EnableOAuth2Sso。

我的问题是,通过上述方法,我只能将一个社交网络用于我的目的(示例中为 google+)。所以,我想知道是否有办法通过在 .yml 文件中以某种方式定义多个社交网络来同时支持多个社交网络。 这是可能的还是我应该使用其他方法?

感谢您的宝贵时间,

克里斯

【问题讨论】:

【参考方案1】:

@EnableOAuth2Sso 功能并非旨在支持多个提供程序作为简单的 YAML 声明。您需要在安全配置中安装 2 个单独的 OAuth2AuthenticationProcessingFilters,而不是使用它,每个都有不同的登录路径,然后从 UI 链接到它们。

【讨论】:

我有类似的需求,并计划在未来拥有一个 AngularJS 前端,以及 mobo 客户端。我很困惑是走这条路,还是使用 Spring Social。了解两者的比较可能会很有帮助。 感谢您的回答(以及您出色的春季项目/模块)戴夫!我使用OAuth2ClientAuthenticationProcessingFilter 和基于OAuth2ProtectedResourceDetails 的其余模板OAuth2RestTemplate 做了一些实验,但我无法在OAuth2 舞蹈的最后一步获得令牌。不过,我将尝试基于这种方法完成代码。与注释相关的另一个问题是:如何使用另一个端口让@EnableOAuth2Sso 使用(例如 9000)? @Sanjay 您对 Spring-Social 有何看法?我正在尝试使用它,但它似乎非常不稳定。我在从官方文档和 github 运行代码时遇到问题! 以前我曾在 Facebook 上尝试过,它发现它运行良好 (github.com/naturalprogrammer/spring-boot-security-social-sample)。但我也感觉到这个项目进展缓慢。似乎重要的错误仍然存​​在很长时间。例如这个 - jira.spring.io/browse/SOCIAL-448 昨天我克隆并运行了你的项目!这是我唯一设法使用和修改的,谢谢!在使用官方示例时遇到问题后,我害怕在自己的项目中使用 Spring-Social 包。我觉得这个项目的创建是为了让程序员在 5 行代码中实现“连接到 Facebook”功能,但如果需要其他任何东西,问题就开始了。【参考方案2】:

我还偶然发现了这个问题以及许多其他关于多身份验证提供程序支持的问题。 Syer 的回答是核心 @EnableOAuth2Sso 注释不是为此而设计的,这实际上非常有帮助。这让我在别处寻找。

受益于 Nimbus OAuth 库,我设计了另一种方法。它可能不干净和漂亮,但它符合我的计划。单独的身份验证提供程序在属性中定义并根据 URI 路径进行选择。

这是我想出的:https://bitbucket.org/klaalo/orcidconnect/src/f3e4fada9827e47bd33efd579fd020c41e37ee2a/src/main/java/fi/csc/orcidconnect/oauth2client/

基本上,提供程序的选择基于DelegatingAuthenticationProviderEndpoint 在 SecurityConfiguration 中做出的决定(在默认包上)。 AuthenticationProcessingFilter 正在等待身份验证事件并重定向到身份验证提供程序。返回时它将验证收到的代码并携带AuthenticationToken 以供自定义AuthenticationProvider 进行评估。

接收到的 UserDetails 被持久化到 Map 中的 User 对象中。

希望这会有所帮助。

【讨论】:

您可能需要编辑以突出显示几个部分以使其清晰。【参考方案3】:

您提供的链接仅显示如何使用启用单个身份验证服务器提供程序的@EnableOAuth2Sso 工具。为了实现多个提供者,您应该遵循:

https://spring.io/guides/tutorials/spring-boot-oauth2/#_social_login_manual

并为每个提供者实现一个过滤器。

【讨论】:

【参考方案4】:

确实,请查看马里奥发布的链接(不知道为什么它被否决..):social_login_manual

链接说@EnableOAuth2Sso 本质上是@EnableOAuth2Client 和一些附加魔法的组合。缺点是您无法轻松自定义其行为以支持多个提供程序。因此,在本教程中,建议将其替换为 @EnableOAuth2Client,并通过一些自定义添加重复 @EnableOAuth2Sso 在后台所做的工作。

所以,它是这样的:

@SpringBootApplication
@EnableOAuth2Client
@RestController
public class SocialApplication extends WebSecurityConfigurerAdapter 

   private Filter ssoFilter() 
      CompositeFilter filter = new CompositeFilter();
      List<Filter> filters = new ArrayList<>();
      filters.add(ssoFilter(facebook(), "/login/facebook"));
      filters.add(ssoFilter(github(), "/login/github"));
      filter.setFilters(filters);
      return filter;
    



 private Filter ssoFilter(ClientResources client, String path) 
      OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(path);
      OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
      filter.setRestTemplate(template);
      filter.setTokenServices(new UserInfoTokenServices(
          client.getResource().getUserInfoUri(), client.getClient().getClientId()));
      return filter;
    

  @Bean
    @ConfigurationProperties("github")
    public ClientResources github() 
      return new ClientResources();
    

  @Bean
    @ConfigurationProperties("facebook")
    public ClientResources facebook() 
      return new ClientResources();
    

class ClientResources 

  @NestedConfigurationProperty
  private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

  @NestedConfigurationProperty
  private ResourceServerProperties resource = new ResourceServerProperties();

  public AuthorizationCodeResourceDetails getClient() 
    return client;
  

  public ResourceServerProperties getResource() 
    return resource;
  


facebook:
  client:
    clientId: 233668646673605
    clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
    accessTokenUri: https://graph.facebook.com/oauth/access_token
    userAuthorizationUri: https://www.facebook.com/dialog/oauth
    tokenName: oauth_token
    authenticationScheme: query
    clientAuthenticationScheme: form
  resource:
    userInfoUri: https://graph.facebook.com/me
github:
  client:
    clientId: bd1c0a783ccdd1c9b9e4
    clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
    accessTokenUri: https://github.com/login/oauth/access_token
    userAuthorizationUri: https://github.com/login/oauth/authorize
    clientAuthenticationScheme: form
  resource:
    userInfoUri: https://api.github.com/user

【讨论】:

以上是关于同时为多个社交网络启用OAuth2Sso的主要内容,如果未能解决你的问题,请参考以下文章

Greenplum 对社交网络/即时通讯应用程序有效吗?

解析适用于 iOS 社交网络应用程序 [关闭]

开发社交网络:技巧、细节和信息

从多个社交网络(Facebook 和 Linkedin...)获取统一配置文件的数据库方案

从网站上的按钮将图像上传到多个社交网络的服务

Python:为社交网络生成图表