述
上文中实现了 ServiceProvider
的部分, 然后剩下就是 ConnectionFactory
创建 Connection
的部分还有与数据量交互的部分
ConnectionFactory 构建
适配器实现
要构建 ConnectionFactory
就需要 ServiceProvider
和一个 ApiAdapter
,ServiceProvider
已经有了,那下面先把 ApiAdapter
实现一下
ApiAdapter
的作用,就是把我们获取回来的第三方的数据,和 social 的标准的数据做一个适配, 新建类 QQAdapter
:
1 | public class QQAdapter implements ApiAdapter<QQ> { |
首先这个类实现了一个 ApiAdapter
接口,泛型是QQ ,这里的泛型就是当前适配器适配的 api 的类型,我们这里要是适配的就是QQ
第一个方法 test
是要去服务提供商是否可以使用,这里就直接返回true了
然后是 setConnectionValues()
方法, 这个就是最主要的方法,作用就是把我们api返回来的数据,设置到 ConnectionValues
里面去fetchUserProfile()
这个方法后面再说
updateStatus()
这个在QQ登录也不需要不用管
ConnectionFactory 实现
到这里,我们的 ServiceProvider
和一个 ApiAdapter
就都有了,这里就可以去构建 ConnectionFactory
了, 新建一个 QQConnectionFactory
,代码如下:
1 | public class QQConnectionFactory extends OAuth2ConnectionFactory<QQ> { |
这里先继承 OAuth2ConnectionFactory
然后写了一个构造, providerId
是服务提供商的id,这个是后面我们自定义去配置的, 然后把 ServiceProvider
和 ApiAdapter
都传过去就好了
数据库层的实现
ConnectionFactory
已经实现了,然后 Connection
就交给 ConnectionFactory
去创建, 最后还剩下的就是数据库层的实现, 这个直接做个配置就好了
首先,数据库需要一个表,sql如下:
1 | CREATE TABLE UserConnection (userId VARCHAR(255) NOT NULL, |
这里表名是固定的 UserConnection
这个不能改,但是可以加一个自定义的前缀, 比如test_UserConnection
表建好之后,就是代码里面的配置,新建类 SocialConfig
:
1 | @Configuration |
这里继承 SocialConfigurerAdapter
然后重写 getUsersConnectionRepository()
方法
这里的参数是 ConnectionFactoryLocator
是用来查询对应的 ConnectionFactory
的,因为我们集成的服务提供商可能有多个, 所以需要找到对应的 ConnectionFactory
然后再看一下构造,前两个就不说了,最后一个 Encryptors
是配置一个加密的方式,是 noOpText()
表示不做加密处理
然后 setTablePrefix()
方法是设置表的前缀, 如果建表的时候有前缀,那这里就写自己的前缀就好
UserDetailService 改造
上面完成之后, QQ登录的流程就算完了, 接下来还有一些配置
之前我们写了一个自定义的 UserDetailService
是 MyUserDetailsService
, 这里面只有一个通过用户名去查找的, 但是第三方登录之后,我们只能通过 userconnection 表 通过 providerId
然后还有 第三方的 openId
去拿到我们业务数据库的 userid, 所以这里还需要一个通过 userId 去查询用户的方法
social提供了他自己的 UserDetailService
是 SocialUserDetailsService
,在之前的 MyUserDetailsService
上实现一下,修改后如下:
1 | @Component |
配置
把用到的一些变量,写到配置类里面, 首先新建 QQProperties
然后继承 SocialProperties
1 | @Data |
SocialProperties
只有两个属性 appId
和 appSecret
,然后自定义一个供应商id ,这里给个默认值是 qq
然后再写一个 SocialProperties
1 | @Data |
最后放到总的配置中 SecurityProperties
1 | @Data |
之后,在 application.yml
中,配置好这些:
1 | core: |
配置 ConnectionFactory
配置类写好之后, 把这些配置给到之前写好的 QQConnectionFactory
, 新建一个 QQAutoConfig
,代码如下:
1 | @Configuration |
这里要注意 @ConditionalOnProperty(prefix = "core.security.social.qq", name = "app-id")
这个注解的作用是
只有找到前缀是 core.security.social.qq
然后名称是 name
的配置有值之后才会生效
浏览器配置
web环境如果想使用 social 的话,还需要把 social
的过滤器加到 security 的过滤器链中去,也就是要把 social
的配置引用过去,首先在 SocialConfig
中,加入以下配置:
1 | @Bean |
然后在浏览器的配置中 BrowserSecurityConfig
,就可以注入 用 apply()
方法引入了, 如下:
1 | @Configuration |
页面配置
最后页面中需要一个三方登录的按钮
1 | <a href = 'auth/qq'>QQ登录</a> |
auth/qq
这个路径,首先 auth
是social的拦截器要拦截前缀, 然后 qq
是我们设置的 providerId
总结
从 ServiceProvider
开始配置然后 ConnectionFactory
的配置, 然后是数据库方面的配置, 按照之前的图,一步一步搞好就ok
掌握 @ConditionalOnProperty
的用法