# scaffold 项目之第三方登陆
# 三方登陆
系统支持对接国内多个第三方平台,实现三方登陆功能。快捷登陆方式。例如:
- 管理后台:企业微信、阿里钉钉
- 用户 App:微信公众号、微信小程序、qq
# 表结构
- 三方登陆完成时,系统会将三方用户存储到
system_social_user
表中,通过type
标记对应的第三方平台。 - 未关联本系统 User 的第三方用户,需要在三方登陆完成后,使用账号密码进行【绑定登陆】,成功后记录到
system_social_user_bind
表中。 - 已关联本系统 User 的第三方用户,在三方登陆完成后,直接进入系统,既
快捷登陆
。
# 绑定登陆
访问登陆页面,点击【钉钉】或者【企业微信】进行第三方登陆。就会调用
/admin-api/system/auth/social-auth-redirect
接口,获取第三方平台的登陆地址,并进行跳转。然后会出现一个二维码,使用【钉钉】或者【企业微信】扫码进行第三方登录。
第三方登录成功后,跳转回
项目访问地址+/social-login
地址。此时,会调用admin-api/system/auth/social-login
接口,尝试【快捷登陆】。由于该三方用户【未关联】管理后台的 AdminUser 用户,此时会看到未绑定账号
的提示,会让用户绑定。接着输入账号密码,提交后进行第三方用户的绑定。此时会调用
admin-api/system/auth/login
接口(在用户名密码的基础上额外带上socialType
+socialCode
+socialState
参数)。成功后,即可进入系统主页。具体实现:
@Override
public String getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri) {
// 获得对应的 AuthRequest 实现
AuthRequest authRequest = buildAuthRequest(socialType, userType);
// 生成跳转地址
String authorizeUri = authRequest.authorize(AuthStateUtils.createState());
return HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri);
}
提示:使用的是 justauth 组件
# 快捷登陆
退出登陆重新登陆
访问登陆页面,点击【钉钉】或者【企业微信】进行第三方登陆。就会调用
/admin-api/system/auth/social-auth-redirect
接口,获取第三方平台的登陆地址,并进行跳转。然后会出现一个二维码,使用【钉钉】或者【企业微信】扫码进行第三方登录。
这个时候会不同(因为已经绑定了用户)第三方登录成功后,跳转回
项目访问地址+/social-login
地址。此时,会调用admin-api/system/auth/social-login
接口,尝试【快捷登陆】。由于该三方用户【已关联】管理后台的 AdminUser 用户,所以会直接进入系统。
# 绑定与解绑
在个人中心进行解除绑定,调用解除的接口删除社交用户
@Override | |
public void deleteSocialClient(Long id) { | |
// 校验存在 | |
validateSocialClientExists(id); | |
// 删除 | |
socialClientMapper.deleteById(id); | |
} |
# 配置管理
# 配置文件
在 application-{env}.yml
( {env}
根据情况使用的是生产环境还是测试环境的配置)配置文件中,对应 justauth
配置项,填写第三方相关的配置信息(appKey 之类的)。
justauth: | |
enabled: true | |
type: | |
DINGTALK: # 钉钉 | |
client-id: dingvrnreajea3yqvzhxg | |
client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOaks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI | |
ignore-check-redirect-uri: true | |
WECHAT_ENTERPRISE: # 企业微信 | |
client-id: wwd411c69a39ada2e54 | |
client-secret: 1wTb7hYxanpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw | |
agent-id: 1000004 | |
ignore-check-redirect-uri: true | |
WECHAT_MINI_APP: # 微信小程序 | |
client-id: ${wx.miniapp.appid} | |
client-secret: ${wx.miniapp.secret} | |
ignore-check-redirect-uri: true | |
ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验 | |
WECHAT_MP: # 微信公众号 | |
client-id: ${wx.mp.app-id} | |
client-secret: ${wx.mp.secret} | |
ignore-check-redirect-uri: true | |
ignore-check-state: true |
# 数据库配置
system_social_client
表,它本质是 justauth组件
配置的存储。
主要有以下几个目的:
方便 client-id 变动,动态修改管理
在需要
SaaS
多租户项目中,通过tenant_id
字段隔离,实现不同租户对应不同的第三方平台的配置在多用户类型的项目中,通过
user_type
字段区分,实现不同用户类型对应不同的第三方平台配置注意:
system_social_client
表的优先级,比application-{env}.yml
配置文件高!
具体实现:
/** | |
* 构建 AuthRequest 对象,支持多租户配置 | |
* | |
* @param socialType 社交类型 | |
* @param userType 用户类型 | |
* @return AuthRequest 对象 | |
*/ | |
private AuthRequest buildAuthRequest(Integer socialType, Integer userType) { | |
// 1. 先查找默认的配置项,从 application-*.yaml 中读取 | |
AuthRequest request = authRequestFactory.get(SocialTypeEnum.valueOfType(socialType).getSource()); | |
Assert.notNull(request, String.format("社交平台(%d) 不存在", socialType)); | |
// 2. 查询 DB 的配置项,如果存在则进行覆盖 | |
SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(socialType, userType); | |
if (client != null && Objects.equals(client.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { | |
// 2.1 构造新的 AuthConfig 对象 | |
AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(request, "config"); | |
AuthConfig newAuthConfig = ReflectUtil.newInstance(authConfig.getClass()); | |
BeanUtil.copyProperties(authConfig, newAuthConfig); | |
// 2.2 修改对应的 clientId + clientSecret 密钥 | |
newAuthConfig.setClientId(client.getClientId()); | |
newAuthConfig.setClientSecret(client.getClientSecret()); | |
// 如果有 agentId 则修改 agentId | |
if (client.getAgentId() != null) { | |
newAuthConfig.setAgentId(client.getAgentId()); | |
} | |
// 2.3 设置会 request 里,进行后续使用 | |
ReflectUtil.setFieldValue(request, "config", newAuthConfig); | |
} | |
return request; | |
} |
系统暂不支持 多租户 + 用户类型 + 社交平台,对应配置,需要进一步扩展实现。
实现方法:
- 加多一个字段
application
存储项目名称,进一步隔离- 前端调用三方登陆额外带
application
参数
在【系统管理】-> 【三方登陆】 -> 【三方应用】 菜单下,可以进行当前租户的 system_soclial_client
表的配置管理。
在【系统管理】-> 【三方登陆】 -> 【三方用户】 菜单下,可以进行当前租户的 system_social_user
三方用户表的查看。
# 第三方平台的申请
可以统一在 justauth 中间件中跳转到各平台进行申请
注意,如果第三方平台如果需要配置具体的授信地址,需要添加 /social-login
用于三方登录回调页、 /user/profile
用于三方用户的绑定与解绑。