使用Guardian实现Elixir应用的身份认证教程
guardian Elixir Authentication 项目地址: https://gitcode.com/gh_mirrors/gu/guardian
前言
在现代Web应用开发中,身份认证是必不可少的功能。本文将详细介绍如何使用Guardian这个强大的Elixir认证库来为你的应用添加安全可靠的认证系统。
Guardian简介
Guardian是一个基于JWT(JSON Web Tokens)的Elixir认证框架,它提供了一套完整的解决方案来处理用户认证和授权。主要特点包括:
- 支持JWT令牌
- 灵活的管道设计
- 多种认证策略
- 易于集成到Phoenix框架
环境准备
首先确保你已经安装了Elixir和Phoenix框架。我们将创建一个新的Phoenix项目作为示例:
mix phx.new auth_demo
添加依赖
在mix.exs文件中添加必要的依赖:
defp deps do
[
{:guardian, "~> 2.3"},
{:argon2_elixir, "~> 2.0"}
]
end
运行mix deps.get
安装依赖。
用户模型
我们需要一个用户模型来存储认证信息。可以使用Phoenix生成器创建:
mix phx.gen.context UserManager User users username:string password:string
这会在数据库中创建users表,包含username和password字段。
密码安全
使用Argon2算法对密码进行哈希处理,修改用户changeset:
def changeset(user, attrs) do
user
|> cast(attrs, [:username, :password])
|> validate_required([:username, :password])
|> put_password_hash()
end
defp put_password_hash(%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset) do
change(changeset, password: Argon2.hash_pwd_salt(password))
end
认证逻辑
实现用户认证函数:
def authenticate_user(username, plain_text_password) do
query = from u in User, where: u.username == ^username
case Repo.one(query) do
nil ->
Argon2.no_user_verify()
{:error, :invalid_credentials}
user ->
if Argon2.verify_pass(plain_text_password, user.password) do
{:ok, user}
else
{:error, :invalid_credentials}
end
end
end
Guardian实现模块
创建Guardian实现模块,这是Guardian的核心配置:
defmodule AuthDemo.UserManager.Guardian do
use Guardian, otp_app: :auth_demo
alias AuthDemo.UserManager
def subject_for_token(user, _claims) do
{:ok, to_string(user.id)}
end
def resource_from_claims(%{"sub" => id}) do
user = UserManager.get_user!(id)
{:ok, user}
rescue
Ecto.NoResultsError -> {:error, :resource_not_found}
end
end
配置Guardian
生成密钥并配置Guardian:
mix guardian.gen.secret
将生成的密钥添加到config.exs:
config :auth_demo, AuthDemo.UserManager.Guardian,
issuer: "auth_demo",
secret_key: "your_generated_secret"
认证管道
创建认证管道来处理HTTP请求:
defmodule AuthDemo.UserManager.Pipeline do
use Guardian.Plug.Pipeline,
otp_app: :auth_demo,
error_handler: AuthDemo.UserManager.ErrorHandler,
module: AuthDemo.UserManager.Guardian
plug Guardian.Plug.VerifySession, claims: %{"typ" => "access"}
plug Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"}
plug Guardian.Plug.LoadResource, allow_blank: true
end
错误处理
实现错误处理模块:
defmodule AuthDemo.UserManager.ErrorHandler do
import Plug.Conn
@behaviour Guardian.Plug.ErrorHandler
@impl Guardian.Plug.ErrorHandler
def auth_error(conn, {type, _reason}, _opts) do
body = to_string(type)
conn
|> put_resp_content_type("text/plain")
|> send_resp(401, body)
end
end
控制器实现
创建会话控制器处理登录/登出:
defmodule AuthDemoWeb.SessionController do
use AuthDemoWeb, :controller
alias AuthDemo.{UserManager, UserManager.Guardian}
def new(conn, _) do
render(conn, "new.html")
end
def login(conn, %{"user" => %{"username" => username, "password" => password}}) do
UserManager.authenticate_user(username, password)
|> login_reply(conn)
end
def logout(conn, _) do
conn
|> Guardian.Plug.sign_out()
|> redirect(to: "/login")
end
defp login_reply({:ok, user}, conn) do
conn
|> put_flash(:info, "Welcome back!")
|> Guardian.Plug.sign_in(user)
|> redirect(to: "/protected")
end
defp login_reply({:error, _reason}, conn) do
conn
|> put_flash(:error, "Invalid credentials")
|> redirect(to: "/login")
end
end
路由配置
最后配置路由:
pipeline :auth do
plug AuthDemo.UserManager.Pipeline
end
pipeline :ensure_auth do
plug Guardian.Plug.EnsureAuthenticated
end
scope "/", AuthDemoWeb do
pipe_through [:browser, :auth]
get "/login", SessionController, :new
post "/login", SessionController, :login
get "/logout", SessionController, :logout
end
scope "/", AuthDemoWeb do
pipe_through [:browser, :auth, :ensure_auth]
get "/protected", PageController, :protected
end
测试认证流程
- 创建迁移并运行:
mix ecto.migrate
- 创建测试用户:
AuthDemo.UserManager.create_user(%{username: "test", password: "password"})
- 启动服务器:
mix phx.server
现在你可以访问:
/login
- 登录页面/protected
- 需要认证的页面/logout
- 登出
总结
通过本教程,我们实现了:
- 用户模型和密码哈希
- Guardian核心配置
- 认证管道和错误处理
- 登录/登出功能
- 受保护路由
Guardian提供了强大而灵活的身份认证解决方案,可以轻松集成到Elixir应用中。你可以在此基础上扩展更多功能,如权限管理、多因素认证等。
guardian Elixir Authentication 项目地址: https://gitcode.com/gh_mirrors/gu/guardian
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考