11 KiB
Halo 认证方式
目前 Halo 支持的认证方式有:
- 基本认证(Basic Auth)
- 表单登录(Form Login)
计划支持的认证方式有:
基本认证
这是最简单的一种认证方式,通过简单设置 HTTP 请求头 Authorization: Basic xxxyyyzzz==
即可实现认证,访问 Halo API,例如:
╰─❯ curl -u "admin:P@88w0rd" -H "Accept: application/json" http://localhost:8090/api/v1alpha1/users
或者
╰─❯ echo -n "admin:P@88w0rd" | base64
YWRtaW46UEA4OHcwcmQ=
╰─❯ curl -H "Authorization: Basic YWRtaW46UEA4OHcwcmQ=" -H "Accept: application/json" http://localhost:8090/api/v1alpha1/users
表单认证
这是一种比较常用的认证方式,只需提供用户名和密码以及 CSRF 令牌
(用于防止重复提交和跨站请求伪造)。
-
表单参数
| 参数名 | 类型 | 说明 | | ---------- | ------ | ------------------------------------- | | username | form | 用户名 | | password | form | 密码 | | _csrf | form |
CSRF
令牌。由客户端随机生成。 | | XSRF-TOKEN | cookie | 跨站请求伪造令牌,和_csrf
的值一致 | -
HTTP 200 响应
仅在请求头
Accept
中包含application/json
时发生,响应示例如下所示:╰─❯ curl 'http://localhost:8090/login' \ -H 'Accept: application/json' \ -H 'Cookie: XSRF-TOKEN=1ff67e0c-6f2c-4cf9-afb5-81bc1015b8e5' \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-raw '_csrf=1ff67e0c-6f2c-4cf9-afb5-81bc1015b8e5&username=admin&password=P@88w0rd'
< HTTP/1.1 200 OK < Vary: Origin < Vary: Access-Control-Request-Method < Vary: Access-Control-Request-Headers < Content-Type: application/json < Content-Length: 161 < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: 0 < X-Content-Type-Options: nosniff < X-Frame-Options: DENY < X-XSS-Protection: 1 ; mode=block < Referrer-Policy: no-referrer < Set-Cookie: SESSION=d04db9f7-d2a6-4b7c-9845-ef790eb4a980; Path=/; HttpOnly; SameSite=Lax
{ "username": "admin", "authorities": [ { "authority": "ROLE_super-role" } ], "accountNonExpired": true, "accountNonLocked": true, "credentialsNonExpired": true, "enabled": true }
-
HTTP 302 响应
仅在请求头
Accept
中不包含application/json
才会发生,响应示例如下所示:╰─❯ curl 'http://localhost:8090/login' \ -H 'Accept: */*' \ -H 'Cookie: XSRF-TOKEN=1ff67e0c-6f2c-4cf9-afb5-81bc1015b8e5' \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-raw '_csrf=1ff67e0c-6f2c-4cf9-afb5-81bc1015b8e5&username=admin&password=P@88w0rd'
< HTTP/1.1 302 Found < Vary: Origin < Vary: Access-Control-Request-Method < Vary: Access-Control-Request-Headers < Location: /console/ < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: 0 < X-Content-Type-Options: nosniff < X-Frame-Options: DENY < X-XSS-Protection: 1 ; mode=block < Referrer-Policy: no-referrer < Set-Cookie: SESSION=9ce6ad3f-7eba-4de5-abca-650b4721c7ac; Path=/; HttpOnly; SameSite=Lax < content-length: 0
未来计划支持“记住我(Remember Me)”功能。
Personal Access Token
背景
Halo 是一款现代化的开源 CMS / 建站系统,为了便于开发者和用户利用 API 访问网站数据,Halo 支持了 Personal Access Token(以下简称 PAT)功能。 用户可以在 Halo 的后台生成 PAT,它是一个随机字符串,用于在 API 请求头里提供验证身份用。Halo 后端在接收请求时会校验 PAT 的值,如果匹配就会允许访问相应的 API 数据。 这种 PAT 机制避免了直接使用用户名密码的安全隐患,开发者可以为每个 PAT 设置访问范围、过期时间等。同时使用随机 PAT 也增加了安全性。这为开发 Halo 插件和应用提供了更安全简便的认证方式。 相比直接暴露服务端 API,这种 PAT 机制也更标准化和安全可控。Halo 在参考业内主流做法的基础上,引入了 PAT,以便于生态系统的开放与丰富。
设计
PAT 以 pat_
开头,剩余部分为随机字符串,随机字符串可以是 JWT、UUID
或其他经过加密的随机字符串。目前,Halo 的实现是 pat_
+ JWT
的形式,例如:
pat_eyJraWQiOiJabUNtcWhJX2FuaFlWQW5aRlVTS0lOckxXRFhqaEp1Nk9ZRGRtcW13Rno4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJhZG1pbiIsInJvbGVzIjpbInN1cGVyLXJvbGUiXSwicGF0X25hbWUiOiJwYXQtYWRtaW4tSVdvbFEiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwOTAvIiwiZXhwIjoxNjk0NjcyMDc5LCJpYXQiOjE2OTQ1ODU3MjAsImp0aSI6IjE3ZWFkNzlkLTRkMjctYjg4NS02YjAzLTM4Y2JlYzQxMmFlMyJ9.xiq36NZIM3_ynBx-l0scGdfX-89aJi6uV7HJz_kNnuT78CFmxD-XTpncK1E-hqPdQSrSwyG4gT1pVO17UmUCoyoAkZKKKVk_seFwxdbygIueo2UJA5kVw1Naf_6iLtNkAXxAiYUpd8ihIwvVedhmOMQ9UUfd4QKZDR1XnTW4EAteWBi7b0pWqSa4h5lv7TpmAECY_KDAGrBRGGhc9AxsrGYPNZo68n2QGJ5BjH29vfdQaZz4vwsgKxG1WJ9Y7c8cQI9JN8EyQD_n560NWAaoFnRi1qL3nexvhjq8EVyGVyM48aKA02UcyvI9cxZFk6ZgnzmUsMjyA6ZL7wuexkujVqmc3iO5plBDCjW7oMe1zPQq-gEJXJU6gdr_SHcGG1BjamoekCkOeNT3CPzA_-5j3AVlj7FTFQkbn_h-kV07mfNO45BVVKsMb08HrN6iEk7TOX7SxN0s2gFc3xYVcXBMveLtftOfXs04SvSFCfTDeJH_Jy-3lYb_GLOji7xSc6FgRbuAwmzHLlsgBT4NJhR_0dZ-jNsCDIQCIC3iDc0qbcNTJYYocT77YaQzIkleFIXyPiV0RsNPmSTEDGiDlctsZ-AmcGCDQ-UmW8SIFBrA93OHncvb47o0-uBwZLdF_we4S90hJlNiAPVhhrBMtCoTJotyrODMEzwbLIukvewFXp8
示例 Token 中 JWT 部分所对应的 Header 如下:
{
"kid": "ZmCmqhI_anhYVAnZFUSKINrLWDXjhJu6OYDdmqmwFz8",
"alg": "RS256"
}
Payload 如下:
{
"sub": "admin",
"roles": [
"super-role"
],
"pat_name": "pat-admin-IWolQ",
"iss": "http://localhost:8090/",
"exp": 1694672079,
"iat": 1694585720,
"jti": "17ead79d-4d27-b885-6b03-38cbec412ae3"
}
使用方式
生成 PAT
Halo 专门提供了生成 PAT 的端口:/apis/api.console.security.halo.run/v1alpha1/users/-/personalaccesstokens
。创建 PAT
请求示例如下:
curl -u admin:admin -X 'POST' \
'http://localhost:8090/apis/api.console.security.halo.run/v1alpha1/users/-/personalaccesstokens' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"spec": {
"name": "My PAT",
"description": "This is my first PAT.",
"expiresAt": "2023-09-15T02:42:35.136Z"
"roles": [""]
}
}'
{
"spec": {
"description": "This is my first PAT.",
"expiresAt": "2023-09-16T02:42:35.136Z",
"roles": [],
"username": "admin",
"revoked": false,
"tokenId": "0b897d9c-56d7-5541-2662-110b70e3f9fd"
},
"apiVersion": "security.halo.run/v1alpha1",
"kind": "PersonalAccessToken",
"metadata": {
"generateName": "pat-admin-",
"name": "pat-admin-lobkm",
"annotations": {
"security.halo.run/access-token": "pat_eyJraWQiOiJabUNtcWhJX2FuaFlWQW5aRlVTS0lOckxXRFhqaEp1Nk9ZRGRtcW13Rno4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJhZG1pbiIsInJvbGVzIjpbXSwicGF0X25hbWUiOiJwYXQtYWRtaW4tbG9ia20iLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwOTAvIiwiZXhwIjoxNjk0ODMyMTU1LCJpYXQiOjE2OTQ3NDcyOTgsImp0aSI6IjBiODk3ZDljLTU2ZDctNTU0MS0yNjYyLTExMGI3MGUzZjlmZCJ9.UVFYzKmz3bUk7fV6xh_CpuNJA-BR8bci-DIJ7o0fk-hayHXFHr_-7HMrVn7iZcphryqmk0RLv7Zsu_AjY9Qn9iCYybBJBycU0tUJzhDexRtj1ViJtlsraoYxLNSYpJK1hcPngeJuiMa9FZrYGp0k_7GX1NddoXLUBI9orN9DbdKmmJXtvigaxPCp52Mu7fBtVsTmO5fk_y2CglqRl_tkLRpFSgUbERKOqKItctDFRg-WUALBYEpXbhZIXBMuTCsJwhniBMpc1Uu_a1Dqa3K5hDgfHTeUADY2BuhEdYJCODPCzmdfWMNqxYSKQT5JFYoDv-ed6cRqNjKeNvd1IPT3RDkVt_fbo8KPrzvkgIjIzni-Wlwe-pXXQbj_n8iax-jkeK526iu8q2CLptxYxLGD0j8htKZramrov4UkK_eIsotEZZfqig9sYVU5_b442WhOWatdB_pbKj7h-YK1Cb2ueg5kl73bcbBu63b8edJZClp6xr72az343SfBZdwrT_JJ5HR0hJmckAMR_U4qvGWrJ-dobXDgY9Oz-qObfiyglzn0Wrz4HRPlmqDFr2o6TMV7UVjQiV77tDzaNbaXVevXGPS5MaZr313dia7XLpIV3QopXma7rDR6Xnqg7ftDQb5vAvsjwN-JsVabAsdFeCo6ejE1slAD9ZQrD88kgfAIuX4"
},
"version": 0,
"creationTimestamp": "2023-09-15T03:08:18.875350Z"
}
}
请求体说明如下表所示:
属性名 | 描述 |
---|---|
name | PAT 名称。必填。 |
description | PAT 描述。非必填。 |
expiresAt | PAT 过期时间,一旦创建不可修改,或修改无效。如果不填写,则表示 PAT 无过期时间。 |
roles | 授权给 PAT 的角色,必须包含在当前用户所拥有的角色内。如果设置为 null 或者 [] ,则表示当前 PAT 仅会拥有 anonymous 和 authenticated 角色。 |
响应体说明如下所示:
属性路径 | 描述 |
---|---|
metadata.annotations.security.halo.run/access-token | 生成好的 PAT。需要注意的是,这个 PAT 不会保存在数据库中,所以仅有一次保存机会。 |
使用 PAT
向 Halo 发送请求时,携带 Header:Authorization: Bearer $PAT
即可。示例如下:
curl http://localhost:8090/apis/api.console.halo.run/v1alpha1/users/- \
-H "Authorization: Bearer pat_eyJraWQiOiJabUNtcWhJX2FuaFlWQW5aRlVTS0lOckxXRFhqaEp1Nk9ZRGRtcW13Rno4IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJhZG1pbiIsInJvbGVzIjpbXSwicGF0X25hbWUiOiJwYXQtYWRtaW4tbG9ia20iLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwOTAvIiwiZXhwIjoxNjk0ODMyMTU1LCJpYXQiOjE2OTQ3NDcyOTgsImp0aSI6IjBiODk3ZDljLTU2ZDctNTU0MS0yNjYyLTExMGI3MGUzZjlmZCJ9.UVFYzKmz3bUk7fV6xh_CpuNJA-BR8bci-DIJ7o0fk-hayHXFHr_-7HMrVn7iZcphryqmk0RLv7Zsu_AjY9Qn9iCYybBJBycU0tUJzhDexRtj1ViJtlsraoYxLNSYpJK1hcPngeJuiMa9FZrYGp0k_7GX1NddoXLUBI9orN9DbdKmmJXtvigaxPCp52Mu7fBtVsTmO5fk_y2CglqRl_tkLRpFSgUbERKOqKItctDFRg-WUALBYEpXbhZIXBMuTCsJwhniBMpc1Uu_a1Dqa3K5hDgfHTeUADY2BuhEdYJCODPCzmdfWMNqxYSKQT5JFYoDv-ed6cRqNjKeNvd1IPT3RDkVt_fbo8KPrzvkgIjIzni-Wlwe-pXXQbj_n8iax-jkeK526iu8q2CLptxYxLGD0j8htKZramrov4UkK_eIsotEZZfqig9sYVU5_b442WhOWatdB_pbKj7h-YK1Cb2ueg5kl73bcbBu63b8edJZClp6xr72az343SfBZdwrT_JJ5HR0hJmckAMR_U4qvGWrJ-dobXDgY9Oz-qObfiyglzn0Wrz4HRPlmqDFr2o6TMV7UVjQiV77tDzaNbaXVevXGPS5MaZr313dia7XLpIV3QopXma7rDR6Xnqg7ftDQb5vAvsjwN-JsVabAsdFeCo6ejE1slAD9ZQrD88kgfAIuX4"