标签:ffline send 分组 curl 命令 nat support image 含义 set
一般场景是三个节点:客户端,服务端,Keycloak
客户端通过 Keycloak 获取一个 Token,再用这个 Token 访问服务端,服务端对 Token 做验证
这里用 Postman 模拟客户端,假设要访问的服务端的 URL 是 192.168.1.1:9090/api/server-name/v1/service-01
以上操作用命令行执行的话命令如下
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
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 的信息)
如果服务端是 Springboot,那么有两种方法验证
继承 ResourceServerConfigurerAdapter 类,这是一个通用的做 OAUTH 2.0 验证的类,验证的 Token 可以不是 Keycloak 发的,只要是符合标准的 Token 就可以,需要配置包括 Realm 的 PublicKey 在内的一些信息,做验证的时候 keycloak 可以没运行,只要 PublicKey 能用于解密就可以
继承 KeycloakWebSecurityConfigurerAdapter 类,这是 springboot 做 keycloak 验证的适配器,需要配 keycloak 的地址和相应的 Realm,不用配 PublicKey,springboot 自己会去拿,第一次验证的时候 keycloak 必须在运行,后续的验证不需要
可用的 API:https://www.keycloak.org/docs-api/7.0/rest-api/index.html
要通过 API 操作,同样需要通过 user 拿先一个 Token,再用这个 Token 去操作 Keycloak,这个 user 要有相应的权限
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
标签:ffline send 分组 curl 命令 nat support image 含义 set
原文地址:https://www.cnblogs.com/moonlight-lin/p/12264142.html