美文网首页
Keycloak 的简单使用

Keycloak 的简单使用

作者: moon_light_ | 来源:发表于2020-02-02 22:31 被阅读0次
    1. 下载并安装 Keycloak
    2. 创建 Realm,Client,User
    • Keycloak 有一个默认的 Master Realm,自己再创建一个 Test Realm
    • 在 Test Realm 下创建一个命名为 resource_01 的 client
      1. 进入 resource_01 的 Settings 页,做以下配置
        (1) 将 Access Type 改为 confidential
        (2) 改为 confidential 后会多出 Authorization Enabled 选项,将其设置为 ON
        (3) Valid Redirect URIs 填 *
        配好后点击 Save 保存
      2. 进入 resource_01 的 Credentials 页,记下 Secret 的值,后面访问这个 client 的时候会用到
      3. 进入 resource_01 的 Roles 页,添加两个 roles,分别命名为 admin 和 operator
    • 在 Test Realm 下创建一个 user_01 的 user
      1. 进入 user_01 的 Credentials 页,将 Temporary 设置为 OFF,然后重置密码
    • 将 client 的 role 和 user 关联
      1. 进入 user_01 的 Role Mappings 页,在 Client Roles 选 resource_01,在 Available Roles 选择 admin,点 Add Selected,意味着 user_01 可以访问 resource_01,并且是 admin 权限,可以再创建一个 user_02 将 role 选为 operator,意味着 user_02 可以访问 resource_01,但只有做基本操作的权限(创建 client 的 role 的时候名字是可以随便写的,严格来讲 resource_01,admin 和 operator 都是什么含义,应该由 server 决定)
    • client 的 role 也可以和其他 client 关联 (这篇文章里没用上)
      1. 进入 client 的 Service Account Roles 页,在 Client Roles -> Available Roles 选择
    3. 通过 Keycloak 做验证

    一般场景是三个节点:客户端,服务端,Keycloak
    客户端通过 Keycloak 获取一个 Token,再用这个 Token 访问服务端,服务端对 Token 做验证

    这里用 Postman 模拟客户端,假设要访问的服务端的 URL 是 192.168.1.1:9090/api/server-name/v1/service-01

    1. 在 Authorization -> TYPE,选 OAuth 2.0
    2. 点 Get New Access Token,各项配置如下
      • Grant Type:Password Credentials
      • Access Token URL:http://localhost:8080/auth/realms/Test/protocol/openid-connect/token
      • Username:user_01
      • Password:user_01 的密码
      • Client ID:resource_01
      • Client Secret:在 resource_01 的 Credentials 页下找
      • Scope:Realm Setting -> General -> Endpoints 点 OpenID Endpoint Configurations 找到 scopes_supported 随便选一个填比如 openid
      • Client Authentication :Send as Basic Auth Header (意思是 Postman 拿到 Token 后是放在 Header 发给服务端)



        点 Request Token,成功获取后点 Use Token

    3. 发送请求给服务端



      实际上发送请求的时候,加上了一个 name 为 Authorization,value 为 Bearer ${token} 的 Header 项

    以上操作用命令行执行的话命令如下

    curl -k -X POST -d "grant_type=password&username=user_01&password=123456&scope=%22openid%22&client_id=resource_01&client_secret=d54d22b0-4941-415d-ba59-79b7ce70498e" http://localhost:8080/auth/realms/Test/protocol/openid-connect/token
    curl -X GET -H "X-Request-With: XMLHttpRequest" -H "content-type: application/json" -H "Authorization: Bearer xxx" -H "api_key: queryOverdueInfo" http://192.168.1.1:9090/api/server-name/v1/service-01
    
    4. Token 的内容

    JWT (Json Web Token) 由三部分组成:header,payload,signature
    从 Keycloak 获取到的 token = base64(header) + "." + base64(payload) + "." + signature
    其中 signature = encrypt( base64(header) + base64(payload) , privateKey)

    可以看到,token 的 header 和 payload 相当于是明文的,只要对相应部分进行解码就可以看到

    服务器端主要用 publicKey 对 signature 部分解密,然后和 header,payload 部分对比,确保 token 是合法的

    每一个 Realm 会有自己的 privateKey 和 publicKey

    对 header 部分和 payload 部分解码,内容如下

    header

    {
        "alg" : "RS256",
        "typ" : "JWT",
        "kid" : "jwQF3Y_V5vCfNSkKtP5XAt9LzdpKKjfjGOEFPZsw8xc"      // key id,密钥 id
    }
    

    payload

    {
        "jti":"df57c8b5-9801-47b3-9977-74a66e9a8d88",         // jwt id
        "exp":1580829682,                                     // 过期时间
        "nbf":0,                                              // 有效起始时间
        "iat":1580829382,                                     // 发行时间
        "iss":"http://localhost:8080/auth/realms/Test",       // 发行者
        "aud":"account",                                      // 受众
        "sub":"0d61a540-4914-4887-ac28-87b21da91da3",         // 主题 
        "typ":"Bearer",
        "azp":"resource_01",                                  // Authorized party
        "auth_time":0,
        "session_state":"1a8a0680-5e6e-40dc-a150-9a84954dbc55",
        "acr":"1",
        "realm_access": {
            "roles":[
                "offline_access",
                "uma_authorization"
            ]
        },
        "resource_access": {
            "resource_01": {
                "roles":[
                    "admin"
                ]
            },
            "account":{
                "roles":[
                    "manage-account",
                    "manage-account-links",
                    "view-profile"
                ]
            }
        },
        "scope":"openid email profile",
        "email_verified":false,
        "preferred_username":"user_01"
    }
    

    服务端验证并解码 token 就可以看到,这个 token 的 username 是 user_01,它有 resource_01 这个 client 的 admin 权限,服务端就可以根据 resource_01,admin 决定是否允许做相应的操作,当然也可以使用其它字段,这都是由服务端自己决定的

    在请求 token 的时候,client id 不一定要填 user_01 关联的 client,比如可以填上 resource_02 及相应的 secret,这也是允许的,这样得到的 token,resource_access 部分依然是 resource_01 以及 admin(假设 user_01 没有同时关联 resource_02),但 azp 部分会变成 resource_02,这种用法的其中一种场景,是可以有一个统一的 client 做入口,比如有一个 client 就叫 resources,不论哪个 user 要访问哪个 resource,获取 token 的时候 client 都统一填 resources 就可以,因为 token 里的 resource_access 字段依然是 user 真正关联的所有 client

    如果请求 token 的时候,Grant Type 选的是 Client Credentials,这样只需要填 client id 和 client secret,不需要填 user 和 password,这样得到的 token,以 resource_01 为例子,会多一个 clientId 字段为 resource_01,而 preferred_username 部分将变成 service-account-resource_01,resource_access 部分还是 resource_01,roles 变成 uma_protection(这是创建 client 时默认就有的 role,如果把这个 role 删除了,那么返回的 token 的 resource_access 字段不会有 resource_01 的信息)

    5. Springboot 验证 Token

    如果服务端是 Springboot,那么有两种方法验证

    • 继承 ResourceServerConfigurerAdapter 类,这是一个通用的做 OAUTH 2.0 验证的类,验证的 Token 可以不是 Keycloak 发的,只要是符合标准的 Token 就可以,需要配置包括 Realm 的 PublicKey 在内的一些信息,做验证的时候 keycloak 可以没运行,只要 PublicKey 能用于解密就可以
    • 继承 KeycloakWebSecurityConfigurerAdapter 类,这是 springboot 做 keycloak 验证的适配器,需要配 keycloak 的地址和相应的 Realm,不用配 PublicKey,springboot 自己会去拿,第一次验证的时候 keycloak 必须在运行,后续的验证不需要
    6. 通过 REST API 操作 Keycloak

    可用的 API:https://www.keycloak.org/docs-api/7.0/rest-api/index.html

    要通过 API 操作,同样需要通过 user 拿先一个 Token,再用这个 Token 去操作 Keycloak,这个 user 要有相应的权限

    1. 创建一个 user 命名为 admin_user
    2. 在 Role Mappings 的 Client Roles 选择 realm-management,把 Available Roles 都加上
    3. 取 Token 的时候 client_id 填 admin-cli
    4. curl 命令如下
    curl -k -X POST -d "grant_type=password&username=admin_user&password=123456&client_id=admin-cli" http://localhost:8080/auth/realms/Test/protocol/openid-connect/token
    



    相关文章

      网友评论

          本文标题:Keycloak 的简单使用

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