2

我正在使用 Guardian 构建我的第一个 Elixir 应用程序,我遇到了用户可以登录并通过身份验证的问题,但是在重定向到下一页时,conn不再存储用户信息并Guardian.Plug.is_authenticated?返回 false。

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)from my方法为刚刚在下的密钥中登录的login用户返回 JSONified User 结构,并且还存储带有令牌的 a。如果您检查after 重定向到,则in 分配的是并且没有。assignscurrent_useruser_tokenconn/userscurrent_userniluser_token

4

1 回答 1

0

HTTP 协议是无状态的。这意味着redirect_to什么都不返回,然后向浏览器返回如何加载另一个(下一个)页面的指令

调用后,auth 请求中的conn与所有存储的用户资源和令牌一起消失redirect

现在浏览器启动到服务器的新连接,这将创建绝对新的conn,它对先前的一无所知(例如,如果一个服务器有集群,则可以由另一台服务器处理)。

那么,如何在连接之间“存储状态”(在我们的例子中是用户资源) ?

当然是饼干。应该在一个请求中将用户令牌放入 cookie 中,并在所有下一个请求中从 cookie 中检索令牌。

公平地说,Guardian有两种不同的方式在 cookie 中存储和检索令牌:直接使用remember_me / VerifyCookie Plug或使用会话:put_session_token / VerifySession Plug

put_session_token在内部自动调用sign_in,因此您的管道应该包含用于会话的插件。

于 2019-06-30T07:40:14.013 回答