Keycloak用户存储SPI实现 [英] Keycloak User Storage SPI Implementation
问题描述
我正在尝试实现自定义密钥克隆Authenticator SPI,以针对外部数据源进行身份验证. Spring boot Rest Service也可用,我也可以使用它.
I'm trying to implement a custom keycloack Authenticator SPI for authenticating against an external Datasource. Spring boot Rest Service is also available, I can also use that.
我要解决的用例是
向用户显示密钥斗篷登录屏幕.提交用户已针对外部数据源进行了验证.
User is presented keycloak login screen. Onsubmission User is validated against external Datasource.
从外部数据源检索一些属性,将其映射到keycloak的ID和访问令牌.
Retrieve some attributes from external datasource, map it to keycloak's id and access token.
还设置了相同用户同时登录多次的用户限制条件.
Also put in a condition of user restriction of same user logging in multiple times at the same time.
我当时在想,可以通过检索keycloak数据源中可用的用户会话信息来解决.如果我使用外部数据源,keycloak是否仍维护会话信息?
I was thinking, it could be solved by retrieving user session information that's available in the keycloak datasource. If i use external datasource, does keycloak still maintain session information?
我遵循了官方指南的第8.3节( https://www.keycloak.org/docs/latest/server_development/index.html#_auth_spi_walkthrough ),它与我所需要的非常相似.
I followed section 8.3 of the official guide (https://www.keycloak.org/docs/latest/server_development/index.html#_auth_spi_walkthrough), which is very similar to what I need.
现在,我按照第11节的规定跳过并开始( https://www.keycloak.org/docs/latest/server_development/index.html#_user-storage-spi )似乎也更合适.
Now i skipped and started as per section 11(https://www.keycloak.org/docs/latest/server_development/index.html#_user-storage-spi) seems more apt as well.
我所做的是从实现自定义身份验证器SPI开始的,认为这不是正确的方法,现在实现了UserStorageProvider.
What I have done is started with implementing custom authenticator SPI thought it isn't the right way and now implemented UserStorageProvider.
/***
* From UserLookupProvider
*/
public UserModel getUserById(String id, RealmModel realm) {
System.out.println("ID: " + id + ":REALM:" + realm);
StorageId storageId = new StorageId(id);
/**
* StorageId.getExternalId() method is invoked to obtain
* the username embeded in the id parameter
*/
String username = storageId.getExternalId();
System.out.println("Name:" + username);
return getUserByUsername(username, realm);
}
/***
* From UserLookupProvider
* This method is invoked by the Keycloak login page when a user logs in
*/
public UserModel getUserByUsername(String username, RealmModel realm) {
System.out.println("USERNAME: " + username + ":REALM:" + realm);
UserModel userModel = loadedUsers.get(username);
if (userModel == null) {
String password = properties.getProperty(username);
if (password != null) {
userModel = createUserModel(realm, username);
System.out.println("New UserModel:");
System.out.println(userModel.toString());
loadedUsers.put(username, userModel);
}
}
return userModel;
}
protected UserModel createUserModel(RealmModel realm, String username) {
return new AbstractUserAdapter(session, realm, model) {
@Override
public String getUsername() {
return username;
}
};
}
遵循文档( https://www.keycloak.org/docs/latest/server_development/index.html#packaging-and-deployment-2 )
我们的提供程序实现的类文件应放在jar中.您还必须在META-INF/services/org.keycloak.storage.UserStorageProviderFactory文件中声明提供程序工厂类.
The class files for our provider implementation should be placed in a jar. You also have to declare the provider factory class within the META-INF/services/org.keycloak.storage.UserStorageProviderFactory file.
这里的问题是:我创建的jar在"META-INF"文件夹中没有services目录,我需要手动创建并添加它吗?
Question here is: jar I created doesn't have services directory inside "META-INF" folder, do I need to create manually and add it?
org.keycloak.examples.federation.properties.FilePropertiesStorageFactory 一旦创建了jar,就可以使用常规的WildFly方式进行部署:将jar复制到deploy/目录或使用JBoss CLI.
org.keycloak.examples.federation.properties.FilePropertiesStorageFactory Once you create the jar you can deploy it using regular WildFly means: copy the jar into the deploy/ directory or using the JBoss CLI.
使用maven创建jar之后,将jar复制到"keycloak-6.0.1 \ standalone \ deployments"文件夹中.但我在用户联合身份列表"中没有看到我的提供商,
After creating jar using maven, copied jar to "keycloak-6.0.1\standalone\deployments" folder. but i don't see my provider in the "User Federation list"
任何建议/帮助将不胜感激!
Any suggestion/help would be greatly appreciated!!
预先感谢您的建议.
推荐答案
-
好吧,您澄清了,您需要一个User Store Provider API.很棒
Ok you clarified you need a User Store Provider API. Great
现在您的第二个问题/挑战":
Now as for your 2nd "Problem/Challenge":
从外部数据源检索一些属性,将其映射到keycloak的ID和访问令牌.需要检索用户的唯一ID并将其作为主题ID添加到jwt中.这就是ID,当此令牌传递给其他服务时,其余服务便可以用来检索ID.
Retrieve some attributes from external datasource, map it to keycloak's id and access token. Need to retrieve users unique id and add it as subject id in the jwt. That's the id, rest of the services can use to retrieve the id, when this token is passed to other services.
为此,您可以做的最好的事情是:
For this, the best you can do is:
-
将这些用户的唯一数据添加为用户属性(请在管理控制台上查看)
Add those user's unique data as users attributes (see them on the Admin console)
在Keycloak上创建一个客户端作用域",并为用户属性"创建一个映射器 将您要(从用户)添加到ID令牌和访问令牌的属性映射.您还需要将您的客户与刚刚创建的客户范围"联系起来.这听起来可能有点令人困惑,但是该视频的素材很棒,我相信它会为您提供很多帮助:
Create a "Client scope" on Keycloak, with a mapper for "user property" to map those properties you'd like to add (from your user) to your Id-token and access-token. You also need to tie your client with your just created "client scope". This may sound a little bit confusing, but this video is great material and I bilieve it'll help you alot: https://www.youtube.com/watch?v=ZxpY_zZ52kU (arround min 6:30 you'll see how to add extra user info to your tokens)
也请检出此页面: https://jwt.io/(当您在其中粘贴编码令牌时,您可以看到它们的内容),这对开发人员来说是个很棒的工具.
also check this page out: https://jwt.io/ (when you paste there encoded tokens, you can see their contents), it is a great tool for developers.
在您提出解决方案时,我将为您安排独特的会话,或者您将其发布为其他问题,因为这是一个不同的问题.
When you advance in your solution I'll help with the unique session, or you post that as a different question, as that's a different problem.
希望有帮助.
这篇关于Keycloak用户存储SPI实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-