Keycloak自定义实现第三方登录
Keycloak自定义实现第三方登录
第三方Oauth登录
- 由于对接的第三方IDP不一定都是标准的openid connect实现,所以都需要根据第三方的Oauth文档进行定制;
Keycloak对于新增Social IDP的实现,都是标准,以及灵活的;
我们完全可以参照 Keycloak 本身已实现的Github LinkedIn等,快速实现我们的需求;
我们这里以酷家乐的Oauth2 接口进行说明
酷家乐 Oauth2接口分析
- 请求code的参数及返回都是标准的,这里无需进行修改
- 换取token接口,由于返回参数进行data的wrap,以及字段名为驼峰的,所以需要对这部分进行修改定制
- 获取用户信息
由于获取用户信息,还需要额外请求用户的OpenId,所以需要对该部分进行修改
定制Provider
提供工程类: KujialeIdentityProviderFactory
工厂类完全可以从GitHubIdentityProviderFactory
拷贝过来,修改成自己 PROVIDER_ID, NAME 以及create自己的Provider
public class GitHubIdentityProviderFactory extends AbstractIdentityProviderFactory<GitHubIdentityProvider> implements SocialIdentityProviderFactory<GitHubIdentityProvider> {public static final String PROVIDER_ID = "github";@Overridepublic String getName() {return "GitHub";}@Overridepublic GitHubIdentityProvider create(KeycloakSession session, IdentityProviderModel model) {return new GitHubIdentityProvider(session, new OAuth2IdentityProviderConfig(model));}@Overridepublic OAuth2IdentityProviderConfig createConfig() {return new OAuth2IdentityProviderConfig();}@Overridepublic String getId() {return PROVIDER_ID;}
}
解析accessToken 以及获取用户信息
解析用户信息
KujialeIdentityProvider 完整代码
public class KujialeIdentityProvider extends AbstractOAuth2IdentityProvider implements SocialIdentityProvider {public static final String AUTH_URL = "https://oauth.kujiale.com/oauth2/show";public static final String TOKEN_URL = "https://oauth.kujiale.com/oauth2/auth/token";public static final String OPENID_URL = "https://oauth.kujiale.com/oauth2/auth/user";public static final String PROFILE_URL = "https://oauth.kujiale.com/oauth2/openapi/user";public static final String DEFAULT_SCOPE = "get_user_info";public static final String OAUTH2_PARAMETER_ACCESS_TOKEN = "accessToken";public KujialeIdentityProvider(KeycloakSession session, OAuth2IdentityProviderConfig config) {super(session, config);config.setAuthorizationUrl(AUTH_URL);config.setTokenUrl(TOKEN_URL);config.setUserInfoUrl(PROFILE_URL);}@Overrideprotected boolean supportsExternalExchange() {return true;}@Overrideprotected String getProfileEndpointForValidation(EventBuilder event) {return PROFILE_URL;}@Overrideprotected String getDefaultScopes() {return DEFAULT_SCOPE;}/*** 提取酷家乐用户信息,转换为keycloak用户实体** @param event* @param profile* @return*/@Overrideprotected BrokeredIdentityContext extractIdentityFromProfile(EventBuilder event, JsonNode profile) {if (!profile.has("d") || profile.get("d").isEmpty()) {throw new NullPointerException("kujiale idp user info response is null " + profile.toString());}JsonNode userNode = profile.get("d");String openId = getJsonProperty(userNode, "openId");if (openId == null || openId.isEmpty()) {throw new NullPointerException("kujiale idp user info is null " + userNode.asText());}BrokeredIdentityContext user = new BrokeredIdentityContext(openId);String userName = userNode.get("userName").asText();user.setUsername(userName);user.setFirstName(userName);user.setIdpConfig(getConfig());user.setIdp(this);AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, userNode, getConfig().getAlias());return user;}/*** 构建获取酷家乐用户信息的请求 暂不支持** @param subjectToken* @param userInfoUrl* @return*/@Overrideprotected SimpleHttp buildUserInfoRequest(String subjectToken, String userInfoUrl) {return SimpleHttp.doGet(userInfoUrl, session).header("Authorization", "Bearer " + subjectToken);}/*** 获取酷家乐用户信息** @param response* @return*/@Overridepublic BrokeredIdentityContext getFederatedIdentity(String response) {String accessToken;try {JsonNode resNode = asJsonNode(response);accessToken = extractTokenFromResponse(resNode.get("d").toString(), OAUTH2_PARAMETER_ACCESS_TOKEN);} catch (Exception ex) {throw new IdentityBrokerException("No access token available in OAuth server response: " + response);}if (accessToken == null) {throw new IdentityBrokerException("No access token available in OAuth server response: " + response);}BrokeredIdentityContext context = doGetFederatedIdentity(accessToken);context.getContextData().put(FEDERATED_ACCESS_TOKEN, accessToken);return context;}protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {BrokeredIdentityContext context = null;try {JsonNode openidResponse = generateOpenIdRequest(accessToken).asJson();String openId = openidResponse.get("d").asText();if (openId == null) {throw new Exception("Can not get openId from kujiale IDP");}JsonNode profile = generateUserInfoRequest(accessToken, openId).asJson();context = extractIdentityFromProfile(null, profile);} catch (Exception ex) {logger.warn("Cannot GetFederatedIdentity from kujiale IDP, error " + ex.getMessage());}return context;}public SimpleHttp generateOpenIdRequest(String accessToken) {SimpleHttp openIdRequest = SimpleHttp.doGet(OPENID_URL, session).param("access_token", accessToken);return openIdRequest;}public SimpleHttp generateUserInfoRequest(String accessToken, String openId) {SimpleHttp openIdRequest = SimpleHttp.doGet(PROFILE_URL, session).param("open_id", openId).param("access_token", accessToken);return openIdRequest;}}
定制属性映射: IdentityProviderMapper
其实属性映射,本质上只是新增个说明,我们的Provider支持 Import Attribute,
所以代码都是模板代码
public class KujialeUserAttributeMapper extends AbstractJsonUserAttributeMapper {private static final String[] cp = new String[]{KujialeIdentityProviderFactory.PROVIDER_ID};@Overridepublic String[] getCompatibleProviders() {return cp;}@Overridepublic String getId() {return "kujiale-user-attribute-mapper";}}
添加META-INF
添加
org.keycloak.broker.social.SocialIdentityProviderFactory
内容为:自己的ProviderFactory全类名
添加
org.keycloak.broker.provider.IdentityProviderMapper
内容为 自己Mapper的全类名
NoClassDefFoundError报错
相关问题链接
https://stackoverflow.com/questions/57778240/noclassdeffounderror-in-a-provider-jar-when-using-a-class-from-org-keycloak-auth
解决方法
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><configuration><archive><manifestEntries><Dependencies>org.keycloak.keycloak-services</Dependencies></manifestEntries></archive></configuration>
</plugin>
部署Provider及配置使用
部署
拷贝到 /standalone/deployments中,重启服务
重启服务后,到 Admin ==> server info 确认新增的Provider生效
配置
新增IDP![](/assets/blank.gif)
设置属性mapper
可以设置默认使用的IDP
第一次登录,会自动创建用户已经,导入对应的属性信息
属性:
关联的IDP信息
Keycloak自定义实现第三方登录相关推荐
- Spring Security OAuth2——自定义OAuth2第三方登录(Gitee)并与UsernamePassword登录关联解决方案
前文:Spring Security OAuth2--自定义OAuth2第三方登录(Gitee) Maven 主要 <!--Spring Security--><dependency ...
- Spring Security OAuth2——自定义OAuth2第三方登录(Gitee)
官方文档 https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-custom-pr ...
- keycloak 自定义登录页面
keycloak 自定义登录页面详细步骤如下: 因为keycloak是jboss开发的,使用FTL后缀开发前端文件,可能根据以下方式实现 keycloak将前端页面分为四类:按类设置主题. •Acco ...
- 这个第三方登录开源工具,支持市面上几乎所有主流平台!好用!
随着微信.支付宝等航母级应用在众人身边的普及,越来越多的应用.网站在登陆的时候除了提供注册用户外,还直接提供第三方登录的方式,也就是直接关联微信.支付宝这类应用,用已有的账号和密码来快速完成当前应用或 ...
- 第三方登录(QQ登录)开发流程详解
一.准备工作 接入QQ登录前,网站需首先进行申请,获得对应的appid与appkey,以保证后续流程中可正确对网站与用户进行验证与授权. 申请appid和appkey的用途 appid :应用的唯一标 ...
- android 第三方登录界面,Android App集成第三方登录与换肤指南
Android App集成第三方登录与换肤指南 文档编辑 概述 本文主要是介绍了如何通过开源框架快速支持QQ和微信登录,并介绍了如何实现app快速换肤 QQ登录接入 APP要支持QQ登录,需要先到腾讯 ...
- 第三方登录如何给前台返回token_如何设计优雅的第三方账号登录?
# 前言 在互联网应用中,我们构建一个网站或APP,如果没有用户,那就没有价值.所以,如何吸引用户注册和登录,是一个重要问题,而这就涉及到账号体系了. 在应用构建初期,用户量较少,那么自建系统的账号体 ...
- .netcore 极速接入第三方登录
新年新气象,趁着新年的喜庆,肝了十来天,终于发了第一版,希望大家喜欢. 如果有不喜欢看文字的童鞋,可以直接看下面的地址体验一下: Github: https://github.com/mrhuo/Mr ...
- Spring Boot 快速集成第三方登录功能
Spring Boot 快速集成第三方登录功能 前言 此 demo 主要演示 Spring Boot 项目如何使用 史上最全的第三方登录工具 - JustAuth 实现第三方登录,包括 QQ 登录.G ...
最新文章
- Hash函数的安全性
- 「小程序JAVA实战」小程序视频上传方法的抽象复用(57)
- 沾包 nagle算法等
- tinyMce在线编辑器内JavaScript实现按Ctrl+S无刷新保存
- 需求工程-软件需求模式读书笔记3
- Django层级模型定义及序列化嵌套的方法
- 【Java调试】通过SqlSessionFactory类对象获取mapper文件内的动态SQL在执行时的完整SQL及参数(2种使用方法+测试Demo及结果)
- 二叉树的基本操作及哈夫曼编码/译码系统的实现
- 不装oracle进行远程连接解决办法 .
- 【theano-windows】学习笔记十八——混合蒙特卡洛采样
- 学习《Building Applications with FME Objects》 之四 从数据集读取要素
- Java Thread 总结
- 127.0.0.1和0.0.0.0和本机IP的区别
- DFN-LOW算法---割点、桥、强连通分量
- zabbix中文乱码的三种解决办法
- 【JAVA】doc,excel,等转pdf,swf
- 高淇java_关于高淇JAVA中SORM总结学习笔记详细个人解释
- php errorcode,errorCode.php
- word实现奇数页页眉用本章标题,偶数页用论文标题
- 关于“2021中国隧道与地下空间大会暨中国(城市)地下空间学会(筹)成立大会”的通知
热门文章
- kali下Eternalblue攻击win7
- shopify js使用liquid配置数据方法
- win7变成xp风格了怎么改回_【让win7变成xp】win7变成xp风格_win7界面变成xp
- 征途手游2新开区服务器维护多久,征途永恒开服表
- 统考英语和计算机可以插u盘吗,统考大学英语B考试技巧 精品
- 惠普p1106打印机安装步骤_【记录】win10中安装惠普HP LaserJet Professional P1106打印机驱动...
- 【STM32】LED初始化基础以及基本使用方法(CT117E电路)
- C++ 动态创建二维数组int** B = new int* [n];
- 漫画本地化母语翻译、审校、嵌字排版 安睿杰翻译
- 电商api—拼多多搜索