美文网首页
iOS Developer的全栈之路 - Keycloak(5)

iOS Developer的全栈之路 - Keycloak(5)

作者: 西西的一天 | 来源:发表于2020-01-12 22:34 被阅读0次

    在上一节中,使用Keycloak保护了SpringBoot的RestAPI,其中的用户和角色都是通过Keycloak内置的web页面进行添加的。在本节中,将使用RestAPI来创建用户并为用户分配角色。

    Create User Endpoint

    创建用户的Endpoint:http://localhost:8080/auth/admin/realms/{realmName}/users,在我的demo中realmName为springboot-integration,所以完整的url为:http://localhost:8080/auth/admin/realms/springboot-integration/users,这是一个POST请求,那么body需要传入是什么呢?通过官方文档,需要的body类型为UserRepresentation,body如下所示:

    {
        "firstName": "xyz",
        "lastName": "xyz",
        "username": "xyz",
        "email": "demo@gmail.com",
        "enabled": "true",
        "credentials": [
            {
                "type": "password",
                "value": "123456",
                "temporary": false
            }
        ],
        "realmRoles": [
            "user"
        ]
    }
    

    通过如上的POST请教会得到一个401的错误,回看url,可以发现只有admin的用户才可创建用户。

    获取Token

    获取admin的token和上节中获取普通用户的token是相同的,url:http://localhost:8080/auth/realms/master/protocol/openid-connect/token,并使用x-www-form-urlencoding编码方式发生post请求,如下图所示:

    admin token.png
    获得access token后,重新发起创建用户的请求,当传入用户名不存在时,便可成功创建用户,成功的response是一个空body,status code为201,表示创建成功。

    通过Keycloak的web登录后,会发现,请求中带有的realmRoles并没有生效,查阅想过issue时,发现这是官方暂不支持的一个参数,链接:https://issues.redhat.com/browse/KEYCLOAK-12460,从comment中看到:

    The rest endpoints have never supported adding roles as part of creating a new user, so changing this to a enhancement request. A contribution to this if tests are included would be welcome.

    若需要这个功能看来只能fork过来改一下了,退而求其次,只能再多发一个请求RoleMappers,这个有点尴尬,如果第一个请求成功,第二请求失败,应该如何处理这个结果呢。希望有时间可以创建这个PR~

    Map a Role To a User

    官方给出的endpoint:http://localhost:8080/auth/admin/realms/{realmName}/users/{userId}/role-mappings/realm
    其中需要一个UserId,而在创建时,返回的response为空,那么又需要一个request来获取UserId:
    http://localhost:8080/auth/admin/realms/springboot-integration/users?username=xyz这是一个GET请求,得到的response如下所示:

    [
        {
            "id": "15c16b3d-dafe-496e-8c9e-98933b4cd518",
            "createdTimestamp": 1578820379997,
            "username": "xyz",
            "enabled": true,
            "totp": false,
            "emailVerified": false,
            "firstName": "xyz",
            "lastName": "xyz",
            "email": "demo2@gmail.com",
            "disableableCredentialTypes": [],
            "requiredActions": [],
            "notBefore": 0,
            "access": {
                "manageGroupMembership": true,
                "view": true,
                "mapRoles": true,
                "impersonate": true,
                "manage": true
            }
        }
    ]
    

    终于拿到了userId,继续添加role:
    http://localhost:8080/auth/admin/realms/springboot-integration/users/15c16b3d-dafe-496e-8c9e-98933b4cd518/role-mappings/realm需要的body,如下所示:

    {
        "roles": [
            {
                "name": "user",
                "clientRole": false
            }
        ]
    }
    

    本以为,可以成功添加,可是直接报错,真的是要吐槽Keycloak的官方文档了。通过chrome的network调试工具,看看在网页端是如何发起添加role的请求的,发现playload的格式是这样的:

    [{
        "id": "66633ad6-7412-4176-aa25-0c1ff67a2180",
        "name": "user",
        "description": "normal user",
        "composite": false,
        "clientRole": false,
        "containerId": "springboot-integration"
    }]
    

    根据文档所述,这些role的字段都不是必须得,如果当前只知道role name,是否可以呢?body中只留下name,发送请求,报错:"error": "Role not found",不禁感叹文档有何用
    所以这些字段都是需要的,那么问题又来了,我们如何找到需要的role呢?这次直接忽略文档,chrome network调试工具走起。
    GET请求http://localhost:8080/auth/admin/realms/springboot-integration/roles可获得当前realm下的所有role。

    [
        {
            "id": "195d5f3e-e805-4f53-88c0-e3589b9172c4",
            "name": "admin",
            "description": "administrator, super user",
            "composite": true,
            "clientRole": false,
            "containerId": "springboot-integration"
        },
        {
            "id": "814d6190-3d69-4e9b-aaae-ef60ae12159e",
            "name": "Member",
            "composite": false,
            "clientRole": false,
            "containerId": "springboot-integration"
        },
        {
            "id": "ac6827fb-51b9-436c-8cb8-852babd4816b",
            "name": "offline_access",
            "description": "${role_offline-access}",
            "composite": false,
            "clientRole": false,
            "containerId": "springboot-integration"
        },
        {
            "id": "98107db5-7f81-4fd9-beb0-ea4fd3d0fccd",
            "name": "uma_authorization",
            "description": "${role_uma_authorization}",
            "composite": false,
            "clientRole": false,
            "containerId": "springboot-integration"
        },
        {
            "id": "66633ad6-7412-4176-aa25-0c1ff67a2180",
            "name": "user",
            "description": "normal user",
            "composite": false,
            "clientRole": false,
            "containerId": "springboot-integration"
        },
        {
            "id": "13bc2555-a3d8-4975-9cce-ae2251bca1b2",
            "name": "Librarian",
            "composite": true,
            "clientRole": false,
            "containerId": "springboot-integration"
        }
    ]
    

    总结

    当需要创建一个用户时,首先需要admin用户的token,之后需要一系列的请求:

    1. 创建用户: http://localhost:8080/auth/admin/realms/springboot-integration/users
    2. 根据用户名,获取当前用户的完整信息: http://localhost:8080/auth/admin/realms/springboot-integration/users?username=xyz
    3. 获取当前realm下所有的role: http://localhost:8080/auth/admin/realms/springboot-integration/roles
    4. 为用户添加role: http://localhost:8080/auth/admin/realms/springboot-integration/users/15c16b3d-dafe-496e-8c9e-98933b4cd518/role-mappings/realm

    真的是一口老血 ~

    相关文章

      网友评论

          本文标题:iOS Developer的全栈之路 - Keycloak(5)

          本文链接:https://www.haomeiwen.com/subject/xelwactx.html