我正在使用Guardian构建我的第一个Elixir应用程序,但遇到一个问题,用户可以登录并通过身份验证,但是在重定向到下一页时,conn
不再存储用户信息,而{{ 1}}返回false。
Guardian.Plug.is_authenticated?
session_controller.ex
....
def create(conn, %{"session" => %{"email" => email, "password" => password}}) do
case PhoenixApp.Auth.authenticate_user(email, password) do
{:ok, user} ->
conn
|> PhoenixApp.Auth.login(user)
|> put_flash(:info, "Welcome back!")
|> redirect(to: "/users")
{:error, _reason} ->
conn
|> put_flash(:error, "Invalid username or password.")
|> render("new.html")
end
end
...
router.ex
...
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
scope "/", PhoenixAppWeb do
pipe_through [:browser]
get "/signup", UserController, :new
get "/login", SessionController, :new
post "/login", SessionController, :create
delete "/logout/:id", SessionController, :delete
end
scope "/", PhoenixAppWeb do
# Protected routes
pipe_through [:browser, :auth]
resources "/users", UserController, except: [:new]
get "/", PageController, :index
end
# Auth pipeline
pipeline :auth do
plug(PhoenixApp.Auth.AuthAccessPipeline)
end
...
auth.ex
...
def login(conn, user) do
conn
|> Guardian.Plug.sign_in(user)
|> assign(:current_user, user)
|> IO.inspect
|> put_user_token(user)
end
...
auth_access_pipeline.ex
我的defmodule PhoenixApp.Auth.AuthAccessPipeline do
@moduledoc false
use Guardian.Plug.Pipeline,
otp_app: :phoenix_app,
error_handler: PhoenixApp.Auth.AuthErrorHandler
plug(Guardian.Plug.Pipeline,
module: PhoenixApp.Guardian,
error_handler: PhoenixApp.Auth.AuthErrorHandler
)
plug(Guardian.Plug.VerifySession, claims: %{"typ" => "access"})
# plug(Guardian.Plug.EnsureAuthenticated)
# plug(Guardian.Plug.LoadResource)
end
方法中的IO.inspect(conn)
为刚刚在login
下的assigns
键中登录的用户返回JSONified User结构,并存储一个{{ 1}}和令牌。如果您在重定向到current_user
后检查user_token
,则分配中的conn
为/users
,并且没有current_user
。
答案 0 :(得分:0)
HTTP协议是无状态的。这意味着redirect_to
只会返回浏览器如何加载另一个(下一个)页面的指令。
redirect
之后,auth请求中的conn 消失,所有存储的用户资源和令牌都消失了。
现在,浏览器启动与服务器的新连接,这将创建一个绝对全新的 con ,该服务器对以前的服务器一无所知(例如,如果有一个集群)。
那么,如何在连接之间 之间“存储状态”(在我们的情况下为用户资源)?
当然带有 cookies 。应该在一个请求中将用户令牌放入cookie中,然后在所有下一个请求中从cookie中检索令牌。
公平地说,监护人有两种不同的方式在cookie中存储和检索令牌:直接通过remember_me / VerifyCookie Plug或会话:put_session_token / VerifySession Plug
put_session_token
在sign_in
内部被自动调用,因此您的管道应包括用于会话的插件。