Guardian 认证库从 0.14 升级到 1.0 的完整指南
guardian Elixir Authentication 项目地址: https://gitcode.com/gh_mirrors/gu/guardian
前言
Guardian 是一个功能强大的 Elixir 认证库,在 1.0 版本中进行了重大架构调整。本文将从技术实现角度,全面解析从 0.14.x 升级到 1.0 版本的关键变化和迁移策略。
架构变化概述
1.0 版本最核心的变化是去中心化的设计理念:
- 不再局限于 JWT:虽然默认仍提供完整的 JWT 功能,但架构已支持自定义令牌类型
- 解耦 Phoenix 和 Plug:这些依赖变为可选,使 Guardian 能更独立地使用
- 模块化设计:从全局单例变为每个应用定义自己的认证模块
实现模块配置
基础实现
0.14 版本是全局配置,1.0 需要定义专属模块:
defmodule MyApp.Guardian do
use Guardian, otp_app: :my_app
# 认证相关配置和回调
end
关键变化:
- 配置从
:guardian
作用域移动到应用命名空间 - 所有 Guardian 调用都通过此模块进行
配置方式升级
1.0 支持更灵活的配置值定义方式:
- 静态值
- 动态函数调用:
{Module, :function, [:args]}
示例对比:
# 0.14
config :guardian, Guardian,
issuer: "MyApp"
# 1.0
config :my_app, MyApp.Guardian,
issuer: {MyApp.Config, :issuer, []}
序列化器重构
序列化器接口更名并增强:
| 0.14 方法 | 1.0 方法 | 变化说明 | |------------------|-------------------------|----------------------| | from_token
| resource_from_claims
| 接收完整 claims 对象 | | for_token
| subject_for_token
| 命名更语义化 |
示例实现:
def subject_for_token(user, _claims) do
{:ok, "User:#{user.id}"}
end
def resource_from_claims(%{"sub" => "User:" <> id}) do
{:ok, MyApp.Repo.get(User, id)}
end
核心 API 变化
令牌操作
# 0.14
Guardian.encode_and_sign(user, "access", %{ttl: {1, :hour}})
# 1.0
MyApp.Guardian.encode_and_sign(
user,
%{},
token_type: "access",
ttl: {1, :hour}
)
主要变更点:
- 操作通过实现模块调用
- 选项参数结构化更清晰
- 令牌类型改为选项参数
令牌交换与刷新
# 0.14 交换
Guardian.exchange(old_token, "refresh", "access")
# 1.0 交换
MyApp.Guardian.exchange(old_token, ["refresh"], "access")
# 0.14 刷新
Guardian.refresh!(old_token)
# 1.0 刷新
MyApp.Guardian.refresh(old_token)
返回格式变为包含新旧令牌和声明的元组。
Plug 集成变更
认证管道
1.0 引入管道概念,集中管理认证流程:
defmodule MyApp.AuthPipeline do
use Guardian.Plug.Pipeline,
otp_app: :my_app,
module: MyApp.Guardian,
error_handler: MyApp.AuthErrorHandler
plug Guardian.Plug.VerifySession
plug Guardian.Plug.VerifyHeader
plug Guardian.Plug.EnsureAuthenticated
end
错误处理简化
从多个回调函数简化为统一的 auth_error
:
defmodule MyApp.AuthErrorHandler do
def auth_error(conn, {type, reason}, _opts) do
# 统一处理所有认证错误类型
end
end
高级功能变更
自定义声明
1.0 提供 build_claims
回调:
def build_claims(claims, user, opts) do
claims = Map.put(claims, "role", user.role)
{:ok, claims}
end
权限系统
权限变为可选模块,配置更灵活:
use Guardian, otp_app: :my_app,
permissions: %{
user: %{
profile: 0b1,
admin: 0b10
}
}
use Guardian.Permissions.Bitwise
权限检查示例:
Guardian.Permissions.Bitwise.ensure_permissions(claims, %{user: [:admin]})
WebSocket 集成
Phoenix 通道支持重构:
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
迁移建议
- 分步迁移:先创建实现模块,逐步替换调用
- 测试覆盖:特别注意错误处理流程
- 性能监控:新版本可能有不同的性能特征
- 文档更新:确保团队了解新的 API 约定
结语
Guardian 1.0 通过模块化设计提供了更大的灵活性,虽然迁移需要一定工作量,但新的架构为复杂认证场景提供了更好的支持。建议开发者仔细评估新特性的价值,制定适合项目的迁移策略。
guardian Elixir Authentication 项目地址: https://gitcode.com/gh_mirrors/gu/guardian
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考