【问题标题】:How to map existing user roles to custom user storage provider in keycloak?如何将现有用户角色映射到 keycloak 中的自定义用户存储提供程序?
【发布时间】:2020-09-08 13:17:48
【问题描述】:

我有一个简单的 Spring Boot 应用程序,它使用 keycloak SSO 和自定义用户存储提供程序。 身份验证在没有用户角色的情况下工作正常。 但我需要知道如何将现有用户角色与自定义用户存储提供程序进行映射。 有谁知道如何将现有用户角色与 keycloak 用户存储提供程序映射?

【问题讨论】:

    标签: spring-boot single-sign-on keycloak


    【解决方案1】:

    终于找到了一种映射角色的方法。

    将角色添加到领域并覆盖 AbstractUserAdapterFederatedStorage.getRoleMappingsgetRoleMappings() 方法。

    public Set<RoleModel> getRoleMappings() {
        Set<RoleModel> roles = new HashSet();
        Iterator rolesItr = userEntity.getRoles().iterator();
    
        while(rolesItr.hasNext()) {
            roles.add(realm.getRole(((Role)rolesItr.next()).getName()));
        }
        return roles;
    }
    

    【讨论】:

      【解决方案2】:

      如果您使用的是user storage SPI,您很可能需要实现 UserLookupProvider 接口 (org.keycloak.storage.user.UserLookupProvider)。

      例如,该接口中的方法之一是UserModel getUserByUsername(String username, RealmModel realm)

      如您所见,该接口中的方法返回一个UserModel 对象。

      UserModel 实现了RoleMapperModel 接口。您只需调用 UserModel::grantRole 方法并传递您想要的角色。

      例子:

      假设您有一个class MyUserDao {...},它从您的数据库中检索用户作为class MyUserModel {...} 实例。

          public UserModel getUserByUsername(String username, RealmModel realm) {
              Optional<MyUserModel> myUserOpt = myUserDao.getUserByUsername(username);
              if (!myUserOpt.isPresent()) 
                 throw new AccessDeniedException();
          
              MyUserModel myUser = myUserOpt .get();
          
              UserModel keycloakUser = mapToKeycloakUserModel(myUser);
          
              for (String roleName: myUser.getRoles())
                 userModel.grantRole(KeycloakModelUtils.getRoleFromString(realm, roleName));
              
              return keycloakUser;
          }
      
          private UserModel mapToKeycloakUserModel(MyUserModel myUser) {...}
      

      请注意,您必须使用 org.keycloak.models.utils.KeycloakModelUtils::getRoleFromString 加载角色,否则 UserModel::grantRole 将尝试重新创建角色,您最终会遇到异常。

      【讨论】:

      • 感谢@otonglet 的回答。问题是将 MyRoleModel 映射到 RoleModel。假设 MyRoleModel 只有 id 和 name。在这种情况下,keycloak 的 RoleModel 接口有点复杂。
      • 当我从 ClientModel 获取角色并执行下面的 grantRole() 时出现错误...“具有相同标识符值的不同对象已与会话关联”
      • @lakshithamadusanka 我的错,我把你带到了 JPA 错误。 stackoverflow.com/a/16246858/1722236 org.keycloak.models.jpa.UserAdapter::grantRole 确实会创建该角色实体。我查找了 org.keycloak.models.utils.KeycloakModelUtils.getRoleFromString(realm, roleName) 以了解如何加载 RoleModel。您必须改为调用 RealmModel::getRole。我更新了我的答案。
      • 我也做了 RealmModel::getRole。但得到了同样的错误。
      • @lakshithamadusanka 你能用 org.keycloak.models.utils.KeycloakModelUtils::getRoleFromString 方法代替 RealModel::getRole 再试一次吗?
      猜你喜欢
      • 2016-11-17
      • 2018-03-09
      • 2019-06-12
      • 2023-01-11
      • 1970-01-01
      • 2010-11-15
      • 2018-04-01
      • 2016-08-31
      • 2019-05-07
      相关资源
      最近更新 更多