Elixir 用户在开始登录后不会持久存在

Elixir 用户在开始登录后不会持久存在,elixir,phoenix-framework,guardian,Elixir,Phoenix Framework,Guardian,我正在使用Guardian构建我的第一个Elixir应用程序,我遇到了一个问题,用户可以登录并通过身份验证,但在重定向到下一页时,conn不再存储用户信息,并且Guardian.Plug.is_authenticated?返回false session\u controller.ex .... def create(conn, %{"session" => %{"email" => email, "password" => password}}) do case

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

session\u 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
  ...
  ...
  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
  ...
  ...
  def login(conn, user) do
   conn
    |> Guardian.Plug.sign_in(user)
    |> assign(:current_user, user)
    |> IO.inspect
    |> put_user_token(user)
  end
  ...
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
router.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
  ...
  ...
  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
  ...
  ...
  def login(conn, user) do
   conn
    |> Guardian.Plug.sign_in(user)
    |> assign(:current_user, user)
    |> IO.inspect
    |> put_user_token(user)
  end
  ...
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
auth.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
  ...
  ...
  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
  ...
  ...
  def login(conn, user) do
   conn
    |> Guardian.Plug.sign_in(user)
    |> assign(:current_user, user)
    |> IO.inspect
    |> put_user_token(user)
  end
  ...
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
auth\u access\u pipeline.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
  ...
  ...
  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
  ...
  ...
  def login(conn, user) do
   conn
    |> Guardian.Plug.sign_in(user)
    |> assign(:current_user, user)
    |> IO.inspect
    |> put_user_token(user)
  end
  ...
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

my
login的
IO.inspect(conn)
方法为刚刚在
中登录的用户返回一个JSONified User结构,该用户在
当前用户下分配
键,并且还存储一个带有令牌的
用户令牌。如果在重定向到
/users
后检查
连接
,则分配中的
当前\u用户
nil
,并且没有
用户\u令牌

HTTP协议是无状态的。这意味着
redirect\u to
不返回任何内容,然后向浏览器返回如何加载另一(下一)页的指令

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

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

那么,如何在连接之间“存储状态”(在本例中为用户资源)

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

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


put\u session\u token
会在
sign\u in
中自动调用,因此管道中应该包含用于会话的插头。

我编辑了我的原始帖子以显示我的身份验证管道,并更新了我的
router.ex
以显示哪些路由现在受到保护,哪些路由没有受到保护。我已尝试在管道中包含用于验证会话的插件,但是如果我这样做,我将在登录并重定向到用户索引后立即收到
无效令牌
消息。我仍然没有在路由器文件中看到管道。问题可能是因为您从浏览器管道中删除了会话插件。受保护的路由正在通过authline进行管道传输:
管道通过[:browser,:auth]
,您的意思是需要其他内容吗?我误解了您的评论,我已扩展了代码以显示
:browser
管道。在生成新的phoenix应用程序后,它不会从默认值进行修改,并且未删除
:fetch\u session
插件。您正在使用
Guardian.plug.sign\u in(user)
。但是文档告诉我们使用
MyApp.Guardian.Plug.sign\u in(用户)
您的代码中有这个模块吗?