目前很多平台都提供了单点登录授权服务器功能,比如我们经常用到的QQ登录、微信登录、新浪微博登录、支付宝登录等。如果我们自己的系统需要调用第三方登录,那么我们就需要实现单点登录客户端,然后跟需要对接的平台调试登录SDK。JustAuth是第三方授权登录的工具类库,对接了国外内数十家第三方登录的SDK,我们在需要实现第三方登录时,只需要集成JustAuth工具包,然后配置即可实现第三方登录,省去了需要对接不同SDK的麻烦。 JustAuth官方提供了多种入门指南,集成使用非常方便。但是如果要贴合我们自有开发框架的业务需求,还是需要进行整合优化。下面根据我们的系统需求,从两方面进行整合:一是支持多租户功能,二是和自有系统的用户进行匹配。

成都创新互联公司一直在为企业提供服务,多年的磨炼,使我们在创意设计,网络营销推广到技术研发拥有了开发经验。我们擅长倾听企业需求,挖掘用户对产品需求服务价值,为企业制作有用的创意设计体验。核心团队拥有超过十载以上行业经验,涵盖创意,策化,开发等专业领域,公司涉及领域有基础互联网服务成都二枢服务器租用托管、app软件开发公司、手机移动建站、网页设计、网络整合营销。
一、JustAuth多租户系统配置
GitEgg多租户功能实现介绍
GitEgg框架支持多租户功能,从多租户的实现来讲,目前大多数平台都是在登录界面输入租户的标识来确定属于哪个租户,这种方式简单有效,但是对于用户来讲体验不是很好。我们更希望的多租户功能是能够让用户无感知,且每个租户有自己不同的界面展示。
GitEgg在实现多租户功能时,考虑到同一域名可以设置多个子域名,每个子域名可对应不同的租户。所以,对于多租户的识别方式,首先是根据浏览器当前访问的域名或IP地址和系统配置的多租户域名或IP地址信息进行自动识别,如果是域名或IP地址存在多个,或者未找到相关配置时,才会由用户自己选择属于哪个租户。
自定义JustAuth配置文件信息到数据库和缓存
在JustAuth的官方Demo中,SpringBoot集成JustAuth是将第三方授权信息配置在yml配置文件中的,对于单租户系统来说,可以这样配置。但是,对于多租户系统,我们需要考虑多种情况:一种是整个多租户系统使用同一套第三方授权,授权之后再由用户选择绑定到具体的租户;另外一种是每个租户配置自己的第三方授权,更具差异化。
出于功能完整性的考虑,我们两种情况都实现,当租户不配置自有的第三方登录参数时,使用的是系统默认自带的第三方登录参数。当租户配置了自有的第三方登录参数时,就是使用租户自己的第三方授权服务器。我们将JustAuth原本配置在yml配置文件中的第三方授权服务器信息配置在数据库中,并增加多租户标识,这样在不同租户调用第三方登录时就是相互隔离的。
1、JustAuth配置信息表字段设计
首先我们通过JustAuth官方Demojustauth-spring-boot-starter-demo 了解到JustAuth主要的配置参数为:
- JustAuth功能启用开关。
- 自定义第三方登录的配置信息。
- 内置默认第三方登录的配置信息。
- Http请求代理的配置信息。
- 缓存的配置信息。
justauth:
# JustAuth功能启用开关
enabled: true
# 自定义第三方登录的配置信息
extend:
enum-class: com.xkcoding.justauthspringbootstarterdemo.extend.ExtendSource
config:
TEST:
request-class: com.xkcoding.justauthspringbootstarterdemo.extend.ExtendTestRequest
client-id: xxxxxx
client-secret: xxxxxxxx
redirect-uri: http://oauth.xkcoding.com/demo/oauth/test/callback
MYGITLAB:
request-class: com.xkcoding.justauthspringbootstarterdemo.extend.ExtendMyGitlabRequest
client-id: xxxxxx
client-secret: xxxxxxxx
redirect-uri: http://localhost:8443/oauth/mygitlab/callback
# 内置默认第三方登录的配置信息
type:
GOOGLE:
client-id: xxxxxx
client-secret: xxxxxxxx
redirect-uri: http://localhost:8443/oauth/google/callback
ignore-check-state: false
scopes:
- profile
- openid
# Http请求代理的配置信息
http-config:
timeout: 30000
proxy:
GOOGLE:
type: HTTP
hostname: 127.0.0.1
port: 10080
MYGITLAB:
type: HTTP
hostname: 127.0.0.1
port: 10080
# 缓存的配置信息
cache:
type: default
prefix: 'demo::'
timeout: 1h
在对配置文件存储格式进行设计时,结合对多租户系统的需求分析,我们需要选择哪些配置是系统公共配置,哪些是租户自己的配置。比如自定义第三方登录的enum-class这个是需要由系统开发的,是整个多租户系统的功能,这种可以看做是通用配置,但是在这里,考虑到后续JustAuth系统升级,我们不打算破坏原先配置文件的结构,所以我们仍选择各租户隔离配置。
我们将JustAuth配置信息拆分为两张表存储,一张是配置JustAuth开关、自定义第三方登录配置类、缓存配置、Http超时配置等信息的表(t_just_auth_config),这些配置信息的同一特点是与第三方登录系统无关,不因第三方登录系统的改变而改变;还有一张表是配置第三方登录相关的参数、Http代理请求表(t_just_auth_source)。租户和t_just_auth_config为一对一关系,和t_just_auth_source为一对多关系。
t_just_auth_config(租户第三方登录功能配置表)表定义:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_just_auth_config
-- ----------------------------
DROP TABLE IF EXISTS `t_just_auth_config`;
CREATE TABLE `t_just_auth_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '租户id',
`enabled` tinyint(1) NULL DEFAULT NULL COMMENT 'JustAuth开关',
`enum_class` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '自定义扩展第三方登录的配置类',
`http_timeout` bigint(20) NULL DEFAULT NULL COMMENT 'Http请求的超时时间',
`cache_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '缓存类型',
`cache_prefix` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '缓存前缀',
`cache_timeout` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '缓存超时时间',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`creator` bigint(20) NULL DEFAULT NULL COMMENT '创建者',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`operator` bigint(20) NULL DEFAULT NULL COMMENT '更新者',
`del_flag` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '租户第三方登录功能配置表' ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
t_just_auth_sourc(租户第三方登录信息配置表)表定义:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_just_auth_source
-- ----------------------------
DROP TABLE IF EXISTS `t_just_auth_source`;
CREATE TABLE `t_just_auth_source` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '租户id',
`source_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '第三方登录的名称',
`source_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '第三方登录类型:默认default 自定义custom',
`request_class` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '自定义第三方登录的请求Class',
`client_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户端id:对应各平台的appKey',
`client_secret` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户端Secret:对应各平台的appSecret',
`redirect_uri` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录成功后的回调地址',
`alipay_public_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '支付宝公钥:当选择支付宝登录时,该值可用',
`union_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否需要申请unionid,目前只针对qq登录',
`stack_overflow_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'Stack Overflow Key',
`agent_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '企业微信,授权方的网页应用ID',
`user_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '企业微信第三方授权用户类型,member|admin',
`domain_prefix` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '域名前缀 使用 Coding 登录和 Okta 登录时,需要传该值。',
`ignore_check_state` tinyint(1) NOT NULL DEFAULT 0 COMMENT '忽略校验code state}参数,默认不开启。',
`scopes` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '支持自定义授权平台的 scope 内容',
`device_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '设备ID, 设备唯一标识ID',
`client_os_type` int(11) NULL DEFAULT NULL COMMENT '喜马拉雅:客户端操作系统类型,1-iOS系统,2-Android系统,3-Web',
`pack_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '喜马拉雅:客户端包名',
`pkce` tinyint(1) NULL DEFAULT NULL COMMENT ' 是否开启 PKCE 模式,该配置仅用于支持 PKCE 模式的平台,针对无服务应用,不推荐使用隐式授权,推荐使用 PKCE 模式',
`auth_server_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'Okta 授权服务器的 ID, 默认为 default。',
`ignore_check_redirect_uri` tinyint(1) NOT NULL DEFAULT 0 COMMENT '忽略校验 {@code redirectUri} 参数,默认不开启。',
`proxy_type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'Http代理类型',
`proxy_host_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'Http代理Host',
`proxy_port` int(11) NULL DEFAULT NULL COMMENT 'Http代理Port',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`creator` bigint(20) NULL DEFAULT NULL COMMENT '创建者',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`operator` bigint(20) NULL DEFAULT NULL COMMENT '更新者',
`del_flag` tinyint(2) NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '租户第三方登录信息配置表' ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
2、使用GitEgg代码生成工具生成JustAuth配置信息的CRUD代码
我们将JustAuth配置信息管理的相关代码和JustAuth实现业务逻辑的代码分开,配置信息我们在系统启动时加载到Redis缓存,JustAuth在调用时,直接调用Redis缓存中的配置。
前面讲过如何通过数据库表设计生成CRUD的前后端代码,这里不再赘述,生成好的后台代码我们放在gitegg-service-extension工程下,和短信、文件存储等的配置放到同一工程下,作为框架的扩展功能。
基础配置:
第三方列表:
3、代码生成之后,需要做初始化缓存处理,即在第三方配置服务启动的时候,将多租户的配置信息初始化到Redis缓存中。
- 初始化的CommandLineRunner类 InitExtensionCacheRunner.java。
/**
* 容器启动完成加载资源权限数据到缓存
* @author GitEgg
*/
@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Component
public class InitExtensionCacheRunner implements CommandLineRunner {
private final IJustAuthConfigService justAuthConfigService;
private final IJustAuthSourceService justAuthSourceService;
@Override
public void run(String... args) {
log.info("InitExtensionCacheRunner running");
// 初始化第三方登录主配置
justAuthConfigService.initJustAuthConfigList();
// 初始化第三方登录 第三方配置
justAuthSourceService.initJustAuthSourceList();
}
}
- 第三方登录主配置初始化方法。
/**
* 初始化配置表列表
* @return
*/
@Override
public void initJustAuthConfigList() {
QueryJustAuthConfigDTO queryJustAuthConfigDTO = new QueryJustAuthConfigDTO();
queryJustAuthConfigDTO.setStatus(GitEggConstant.ENABLE);
ListjustAuthSourceInfoList = justAuthConfigMapper.initJustAuthConfigList(queryJustAuthConfigDTO);
// 判断是否开启了租户模式,如果开启了,那么角色权限需要按租户进行分类存储
if (enable) {
Map> authSourceListMap =
justAuthSourceInfoList.stream().collect(Collectors.groupingBy(JustAuthConfigDTO::getTenantId));
authSourceListMap.forEach((key, value) -> {
String redisKey = AuthConstant.SOCIAL_TENANT_CONFIG_KEY + key;
redisTemplate.delete(redisKey);
addJustAuthConfig(redisKey, value);
});
} else {
redisTemplate.delete(AuthConstant.SOCIAL_CONFIG_KEY);
addJustAuthConfig(AuthConstant.SOCIAL_CONFIG_KEY, justAuthSourceInfoList);
}
}
private void addJustAuthConfig(String key, ListconfigList) {
MapauthConfigMap = new TreeMap<>();
Optional.ofNullable(configList).orElse(new ArrayList<>()).forEach(config -> {
try {
authConfigMap.put(config.getTenantId().toString(), JsonUtils.objToJson(config));
redisTemplate.opsForHash().putAll(key, authConfigMap);
} catch (Exception e) {
log.error("初始化第三方登录失败:{}" , e);
}
});
}
- 第三方登录参数配置初始化方法。
/**
* 初始化配置表列表
* @return
*/
@Override
public void initJustAuthSourceList() {
QueryJustAuthSourceDTO queryJustAuthSourceDTO = new QueryJustAuthSourceDTO();
queryJustAuthSourceDTO.setStatus(GitEggConstant.ENABLE);
ListjustAuthSourceInfoList = justAuthSourceMapper.initJustAuthSourceList(queryJustAuthSourceDTO);
// 判断是否开启了租户模式,如果开启了,那么角色权限需要按租户进行分类存储
if (enable) {
Map> authSourceListMap =
justAuthSourceInfoList.stream().collect(Collectors.groupingBy(JustAuthSourceDTO::getTenantId));
authSourceListMap.forEach((key, value) -> {
String redisKey = AuthConstant.SOCIAL_TENANT_SOURCE_KEY + key;
redisTemplate.delete(redisKey);
addJustAuthSource(redisKey, value);
});
} else {
redisTemplate.delete(AuthConstant.SOCIAL_SOURCE_KEY);
addJustAuthSource(AuthConstant.SOCIAL_SOURCE_KEY, justAuthSourceInfoList);
}
}
private void addJustAuthSource(String key, ListsourceList) {
MapauthConfigMap = new TreeMap<>();
Optional.ofNullable(sourceList).orElse(new ArrayList<>()).forEach(source -> {
try {
authConfigMap.put(source.getSourceName(), JsonUtils.objToJson(source));
redisTemplate.opsForHash().putAll(key, authConfigMap);
} catch (Exception e) {
log.error("初始化第三方登录失败:{}" , e);
}
});
}
4、引入JustAuth相关依赖jar包
- 在gitegg-platform-bom工程中引入JustAuth包和版本,JustAuth提供了SpringBoot集成版本justAuth-spring-security-starter,如果简单使用,可以直接引用SpringBoot集成版本,我们这里因为需要做相应的定制修改,所以引入JustAuth基础工具包。
······


咨询
建站咨询
