Пользователь не сохраняется после входа в систему - PullRequest
2 голосов
/ 29 июня 2019

Я создаю свое первое приложение Elixir с использованием Guardian, и у меня возникла проблема, когда пользователь может войти в систему и пройти аутентификацию, но при перенаправлении на следующую страницу conn больше не сохраняет информацию о пользователе и 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 возвращает структуру JSONified User для пользователя, который только что вошел в ключ assigns в current_user, а также сохраняет user_token с токеном. Если вы проверяете conn после перенаправления на /users, current_user в назначениях будет nil, а user_token нет.

1 Ответ

0 голосов
/ 30 июня 2019

Протокол HTTP не имеет состояния.Это означает, что redirect_to ничего не возвращает, тогда инструкция для браузера, как загрузить другую (следующую) страницу .

conn в запросе на аутентификацию исчезает со всемисохраненные пользовательские ресурсы и токены после вызова redirect.

Теперь браузер инициирует новое подключение к серверу, что создает абсолютно новый conn , который ничего не знает о предыдущем (и может, например, обрабатываться другим сервером, если онесть кластер).

Итак, как «сохранить состояние» (в нашем случае - пользовательский ресурс) между соединениями?

с куки конечно.Нужно поместить пользовательский токен в cookie в одном запросе и извлекать токен из cookie во всех последующих запросах.

Честно говоря, Guardian имеет два разных способадля хранения и извлечения токена в / из cookie: непосредственно с Remember_me / VerifyCookie Plug или с сессиями: put_session_token / VerifySession Plug

put_session_token автоматически вызывается внутри sign_in, поэтому в конвейеры должны быть включены заглушки для работы с сеансами.

...