Ueberauth/Guardian 从 0.14.x 升级到 1.0 的完整指南
guardian Elixir Authentication 项目地址: https://gitcode.com/gh_mirrors/gu/guardian
前言
Ueberauth/Guardian 是一个强大的 Elixir 身份验证库,在 1.0 版本中进行了重大架构调整。本文将从技术实现角度,详细介绍从 0.14.x 升级到 1.0 版本的关键变化和迁移步骤。
核心架构变化
1.0 版本最大的变化是解耦了与 JWT 的强绑定关系,虽然默认仍提供完整的 JWT 功能,但现在已经支持自定义令牌类型。同时移除了对 Phoenix 和 Plug 的强制依赖,使得 Guardian 可以更独立地使用。
实现模块的引入
在 0.14.x 中,Guardian 是全局唯一的实现。1.0 版本要求开发者定义一个专门的模块来存放所有认证相关的配置和逻辑。
创建实现模块
defmodule MyApp.Guardian do
use Guardian, otp_app: :my_app
# 这里添加你的认证逻辑
end
这个模块将作为序列化器,同时也是放置 Hooks 的地方。
配置变更
配置方式有了显著改进,现在支持更灵活的配置值定义:
- 可以指定模块函数调用:
{MyModule, :func, [:some, :args]}
- 也可以直接使用静态值
配置位置变化
0.14.x 版本:
config :guardian, Guardian,
# 配置项
1.0 版本:
config :my_app, MyApp.Guardian,
# 配置项
新增的重要配置项包括:
token_verify_module
:验证声明的模块token_ttl
:令牌生存时间的映射%{<token_type> => <ttl_value>}
序列化器重命名
0.14.x 中的 from_token
和 for_token
函数已被重命名并移动到实现模块中:
defmodule MyApp.Guardian do
use Guardian, otp_app: :my_app
def subject_for_token(resource, _claims) do
{:ok, to_string(resource.id)}
end
def resource_from_claims(claims) do
{:ok, find_me_a_resource(claims["sub"])}
end
end
新函数名 subject_for_token
和 resource_from_claims
更加语义化,且接收的参数更完整。
令牌操作变更
创建和验证令牌
0.14.x:
Guardian.encode_and_sign(resource, [token_type, claims])
Guardian.decode_and_verify(token, [claims_to_check])
1.0:
MyApp.Guardian.encode_and_sign(resource, [claims, options])
MyApp.Guardian.decode_and_verify(token, [claims_to_check, options])
令牌类型指定
0.14.x:
Guardian.encode_and_sign(resource, "other_type")
1.0:
MyApp.Guardian.encode_and_sign(resource, %{}, token_type: "other_type")
TTL 设置
0.14.x:
Guardian.encode_and_sign(resource, %{ttl: {1, :hour}})
1.0:
MyApp.Guardian.encode_and_sign(resource, %{}, token_ttl: {1, :hour})
管道(Pipeline)系统
1.0 版本引入了管道概念,用于定义认证流程:
defmodule MyApp.Guardian.AuthPipeline do
@claims %{typ: "access"}
use Guardian.Plug.Pipeline,
otp_app: :my_app,
module: MyApp.Guardian,
error_handler: MyApp.Guardian.AuthErrorHandler
plug Guardian.Plug.VerifySession, claims: @claims
plug Guardian.Plug.VerifyHeader, claims: @claims, realm: "Bearer"
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, allow_blank: false
end
这个管道会:
- 从会话或头部查找令牌
- 验证令牌类型必须为 "access"
- 确保找到令牌
- 加载令牌对应的资源
错误处理简化
错误处理模块被大幅简化,现在只需要实现一个函数:
auth_error(conn, {failure_type, reason}, opts)
内置的错误类型包括:
:invalid_token
:unauthorized
:unauthenticated
:already_authenticated
:no_resource_found
自定义声明
1.0 版本提供了更灵活的自定义声明方式,可以在实现模块中添加 build_claims
回调:
def build_claims(claims, resource, opts) do
new_claims = do_things_to_claims(claims)
{:ok, claims}
end
钩子(Hooks)系统
Hooks 模块已被移除,改为在实现模块中定义回调函数:
after_encode_and_sign
after_sign_in
before_sign_out
on_verify
on_revoke
on_refresh
on_exchange
build_claims
WebSocket/Channel 支持
Phoenix Socket 和 Channel 的宏已被移除,改为提供一组轻量级函数:
defmodule MyApp.UserSocket do
use Phoenix.Socket
def connect(%{"guardian_token" => token}, socket) do
case Guardian.Phoenix.Socket.authenticate(socket, MyApp.Guardian, token) do
{:ok, authed_socket} -> {:ok, authed_socket}
{:error, _} -> :error
end
end
end
权限系统改进
权限系统现在是可选的,并改名为更清晰的 Guardian.Permissions.Bitwise
。
定义权限
use Guardian, otp_app: :my_app,
permissions: %{
user_actions: %{
books: 0b1,
fitness: 0b100,
music: 0b1000
}
}
use Guardian.Permissions.Bitwise
使用权限
# 检查所有权限
has_all? = Guardian.all_permissions?(claims, %{user_actions: [:books]})
# 检查任意权限
has_any? = Guardian.any_permissions?(claims, %{user_actions: [:books, :music]})
在 Plug 中使用
plug Guardian.Permissions.Bitwise, ensure: %{user_actions: [:books]}
总结
1.0 版本带来了更灵活的架构设计,虽然需要一定的迁移工作,但提供了更好的扩展性和更清晰的API设计。建议开发者仔细测试迁移后的系统,特别是自定义声明和权限相关的功能。
guardian Elixir Authentication 项目地址: https://gitcode.com/gh_mirrors/gu/guardian
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考