这一节,我们要研究SpringBoot2+SpringSecuritySocial来实现第三方登录-QQ登录
开发QQ登录思路
我们先看上一章的图

我们最后需要Connection,即QQ登录后的用户信息,想要Connection,就需要ConnectionFactory,想要ConnectionFactory,就需要我们自己实现APIAdapter和ServiceProvider,对于ServiceProvider来说,我们需要自己实现Api,而对于OAuth2Operations可以使用它默认实现的OAuth2Template。
所以,我们的开发流程为:
- 自己实现
Api - 使用默认的
OAuth2Operations,从而实现ServiceProvider - 实现
ApiAdapter,从而实现ConnectionFactory - 在
DB建表,使用默认的UsersConnectionRepository - 这样就可以在容器中通过
ConnectionFactory注入Connection使用了
实现QQ登录
准备工作
https://wiki.connect.qq.com/,到QQ互联官网查看文档,了解QQ登录需要哪些信息,如何获取这些信息,调用哪些接口,传入什么参数,返回什么结果,比较重要的有:
- 获取用户信息
- 获取OpenID
- 获取Access_Token
Api实现
实现Api前,我们先看看AbstractOAuth2ApiBinding的源码
1 | public abstract class AbstractOAuth2ApiBinding implements ApiBinding, InitializingBean { |
重要的成员变量有两个:
accessToken:我们知道Api是第六步,这个Token就是前五步执行完后的令牌,即认证服务器认证后的标志,对于每个线程,每个用户来说,令牌都是不一样的,所以这个是多实例的RestTemplate:向不同第三方登录接口发送请求的Template类,使用Restful形式发送请求
创建QQ接口
1 | public interface QQ { |
接口化,具体实现由QQImpl实现
创建QQUserInfo的Bean
1 | public class QQUserInfo { |
这里就是从QQ互联的文档中查看的
实现QQ接口
1 | public class QQImpl extends AbstractOAuth2ApiBinding implements QQ { |
这里我们详细说一下,其实注释也很清楚了
首先需要继承AbstractOAuth2ApiBinding抽象类,实现他的抽象方法getUserInfo()
我们从QQ互联文档可知,使用QQ接口获取对象,需要accessToken(授权),appId(qq互联的开发ID),openId(用户Id),对于accessToken是由Oauth2Operations提供的,appId因为是QQ互联注册时给的开发者ID所以肯定是配置的,后面传入的,所以这里我们主要获取openId。
根据文档,我们需要发送GET请求来获取openId,这一阶段我们在实例化的时候进行
然后我们通过GET请求再获取用户信息,即实现抽象方法getUserInfo()时进行
这里我使用了阿里的FastJson进行转换,Maven依赖添加一些即可
ServiceProvider实现
我们有了API的QQ实现,对于OAuth2Operations我们使用默认的OAuth2Template,所以我们就可以构造出ServiceProvider了:
1 | public class QQServiceProvider extends AbstractOAuth2ServiceProvider<QQ> { |
这里实现也很简单,继承AbstractOAuth2ServiceProvider抽象类,并配置QQ互联的两个获取认证的地址即可
ConnectionFactory实现
想要实现ConnectionFactory,需要两个,ServiceProvider我们已经有了,就需要实现ApiAdapter了
实现ApiAdapter
这里我们需实现ApiAdapter接口,我们之前就了解到,Adapter是对用户信息进行适配的,将获取到的第三方用户信息赋值到Connection上,所以代码也很简单,如下:
1 | public class QQAdapter implements ApiAdapter<QQ> { |
有了ApiAdapter的实现,我们就可以实现ConnectionFactory了
1 | public class QQConnectionFactory extends OAuth2ConnectionFactory<QQ> { |
代码非常简单,就是通过ProviderID(服务提供商ID),ServiceProvider(QQServiceProvider),ApiAdapter实现即可。
UsersConnectionRepository实现
注入JdbcUsersConnectionRepository
上面绝大部分都实现完毕了,还有一个数据库相关的需要实现,这里我们使用JdbcUsersConnectionRepository,配置的方式是通过配置SocialConfigurerAdapter来进行注入:
1 |
|
数据库建映射表
建表语句我们可以通过查看JdbcUsersConnectionRepository源码位置来获取

1 | create table UserConnection (userId varchar(255) not null, |
向容器添加ConnectionFatory
因为不同的第三方登录方式不同,所以注入方式也不同,这里我们新创建一个配置类,并继承上面写的SocialConfig配置类:
1 |
|
实现SocialUserDetailsService
这里我们注入了Connection,但是还有一个问题:我们之前做好了数据库映射,现在可以通过Connection获取本应用userId但是我们还需要写一个实现,来通过本应用用户ID获取UserDetails,就和之前表单登录时一样。
代码很简单,在之前学习表单登录时实现UserDetailsService,在使用Social时需要实现SocialUserDetailsService,其业务逻辑都是和之前一样的
1 |
|
Security中配置Social过滤器
这里我们还需将SocialAuthenticationFilter加到过滤器链中,首先我们要把SpringSocialConfigurer注入到容器中,因为这里包含了Social过滤器的配置
1 |
|
这里直接加在之前写的SocialConfig配置类中就好
然后再SpringSecurity的配置类中添加social的配置
1 |
|
这里一些之前的配置我们都进行了省略,最重要就是追加SpringSocial的配置
前端页面
1 |
|
这里为什么使用"/auth/qq"呢?我们也没有去配置这个路径,因为SocialAuthenticationFilter默认拦截/auth下的路径,而qq是我们的providerId


我们这样配的话,当请求/auth/qq时,会先被SocialAuthenticationFilter过滤器拦截,然后使用我们创建的QQConnectionFactory来走oauth2流程+构建Connection对象。
启动测试

会发现登录失败,非法重定向,到这里我们已经成功了一半了
下一章我们会通过代码,一点点解决问题,直到成功使用QQ登录