Springboot集成第三方登录(facebook,linkedin,github)

OAuth2.0的第三方登录集成

本文处理方式适用于java服务端REST API

一,了解OAuth2.0

OAuth2.0是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。
而且本文涉及到的授权模式都是采用授权码模式(authorization code):这里写图片描述
它的步骤如下:

(A)用户访问客户端,后者将前者导向认证服务器。
(B)用户选择是否给予客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的”重定向URI”(redirection URI),同时附上一个授权码。
(D)客户端收到授权码,附上早先的”重定向URI”,向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

下面是上面这些步骤所需要的参数。
A步骤中,客户端申请认证的URI,包含以下参数:

  • response_type:表示授权类型,必选项,此处的值固定为”code”
  • client_id:表示客户端的ID,必选项
  • redirect_uri:表示重定向URI,可选项
  • scope:表示申请的权限范围,可选项
  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

C步骤成功后,会返回一个授权码给你,即code,比如:
http://localhost:8091/b2bbuyer/thirdUser?code=AQSHW3H0TNFil9BaO3YgQut7yKW24nit9gz0VWuU7qPDg99tI7S9Vfh9QArtWPLAvsMMzOAkLosUt0USsDZ24iwSWVwpWaHIccVqpirVeNMS84-0vr0&state=987654321
此处你拿到code,就可以进行D步骤了。
E步骤会返回一个access_token,表示访问令牌。通过这个令牌,就可以进行获取信息操作了,比如:
请求Facebook获取email,firstname,lastname

二,获取应用参数

那么现在,我们就来以linkedin为例,开始配置一个应用吧。

1,使用linkedin账户登陆linkedin开发者中心,在My Apps下面创建一个自己的应用,并配置好授权重定向网址:

我的linkedin配置

2,保存验证密钥:

验证密钥
客户端编号: 81y22zvqidpz3
客户端密码: kDdSjSaCQeNt2nU

三,手动获取登录信息

1,在浏览器请求url:https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=81y22zvqid2pz3&redirect_uri=http://localhost:8091/loginn/linkedin&state=987654321,client_id就是刚刚申请的应用的客户端编号。

2,在跳转的页面输入linkedin账号和密码,确认授权之后,会跳转到刚才传的redirect_uri,并且带上code,example:

http://localhost:8091/b2bbuyer/thirdUser?code=AQSHW3H0TNFil9BaO3YgQut7yKW24nit9gz0VWuU7qPDg99tI7S9Vfh9QArtWPLAvsMMzOAkLosUt0USsDZ24iwSWVwpWaHIccVqpirVeNMS84-0vr0&state=987654321

3,拿到code,20秒内在postman中发送请求,example:

这里写图片描述

4,用获取的access_token,在postman中请求,example:

这里写图片描述
结果如下:

{
“firstName”: “阿兰”,
“formattedName”: “冯阿兰 (Alan Feng)”,
“id”: “OBXrP4h10N”,
“lastName”: “冯”,
“numConnections”: 1
}

四,使用Spring Cloud OAuth2

1,阅读Spring官方的Spring boot 集成OAuth2文档,download code from github.

2,引入注解@EnableOAuth2Client,添加application.yml配置文件。example:
application.yml

3,读取配置文件参数:

class ClientResources {

    @NestedConfigurationProperty
    private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

    @NestedConfigurationProperty
    private ResourceServerProperties resource = new ResourceServerProperties();

    public AuthorizationCodeResourceDetails getClient() {
        return client;
    }

    public ResourceServerProperties getResource() {
        return resource;
    }
}

4,添加filter

private Filter ssoFilter(ClientResources client, String path) {
        ExtOAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationFilter = new ExtOAuth2ClientAuthenticationProcessingFilter(
                path);
        oAuth2ClientAuthenticationFilter.setAuthenticationSuccessHandler(successHandler());

        oAuth2ClientAuthenticationFilter.setAuthenticationFailureHandler(failureHandler());

        OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
        oAuth2ClientAuthenticationFilter.setRestTemplate(oAuth2RestTemplate);
        ExtUserInfoTokenServices tokenServices = new ExtUserInfoTokenServices(client.getResource().getUserInfoUri(),
                client.getClient().getClientId());
        tokenServices.setRestTemplate(oAuth2RestTemplate);
        oAuth2ClientAuthenticationFilter.setTokenServices(tokenServices);
        return oAuth2ClientAuthenticationFilter;
    }
@Bean
    @ConfigurationProperties("linkedin")
    public ClientResources linkedin() {
        return new ClientResources();
    }

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

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

最后,在configure方法里,把filter添加进去:

http.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);

五,集成Spring security问题处理

1,如何跳转到前端指定的url,而不是OAuth默认的链接

2,HeaderHttpSessionStrategy的方式会使无法保存授权通过的session

3,如何区分第三方登录的类型(Facebook or linkedin)

4,如何将拿到的登录信息写入Authentication的Principal

5,OAuth2如何将token信息写入redis

以上问题,以后作解

猜你喜欢

转载自blog.csdn.net/iverson2010112228/article/details/53673132