0

我有一个凤凰应用程序,我想保护除登录和用户创建路线之外的所有路线。为此,我使用 Guardian 和 ComeOnIn 包。(我试图关注这个博客)
我设法在会话路由中向客户端发送了一个令牌,并且用户的创建也在工作。
但是,当我想显示所有用户(即用户模块的索引路由)时,我得到一个身份验证错误(在我的测试中,我还没有 gui)
这是我所做的:用户控制器:

defmodule WarehouseWeb.UserController do
  use WarehouseWeb, :controller

  alias Warehouse.Account
  alias Warehouse.Account.User

  action_fallback WarehouseWeb.FallbackController

  def index(conn, _params) do
    users = Account.list_users()
    render(conn, "index.json-api", data: users)
  end
# ... ...
end

这是router.ex

defmodule WarehouseWeb.Router do
  use WarehouseWeb, :router

  pipeline :api do
    plug :accepts, ["json", "json-api"]
  end

  pipeline :api_auth do
    plug WarehouseWeb.Guardian.AuthPipeline
  end

  scope "/api", WarehouseWeb do
    pipe_through :api
    post "/register", RegistrationController, :create
    post "/token", SessionController, :create, as: :login
  end

  scope "/api", WarehouseWeb do
    pipe_through :api_auth

    resources "/users", UserController, except: [:new, :edit]
  end
end

以下是 Guardian 所需的模块:

defmodule WarehouseWeb.Guardian.AuthPipeline do
  use Guardian.Plug.Pipeline, otp_app:       :warehouse,
                              module:        WarehouseWeb.Guardian,
                              error_handler: WarehouseWeb.Guardian.AuthErrorHandler

  plug Guardian.Plug.VerifyHeader
  plug Guardian.Plug.EnsureAuthenticated
end

defmodule Warehouse.Guardian do
  use Guardian, otp: :warehouse,
                secret_key: "some secret"

  def subject_for_token(resource, _claims) do
    {:ok, to_string(resource.id)}
  end
  def resource_from_claims(claims) do
    user = Warehouse.Account.get_user!(claims["sub"])
    {:ok,  user}
  end
end

错误处理程序:

defmodule WarehouseWeb.Guardian.AuthErrorHandler do
  import Plug.Conn

  def auth_error(conn, {type, reason}, opts) do
    IO.inspect "authentication is not working!!"
    body = Poison.encode!(%{message: to_string(type)})
    send_resp(conn, 401, body)
  end
end

最后是我的测试文件:

defmodule WarehouseWeb.UserControllerTest do
  use WarehouseWeb.ConnCase

  alias Warehouse.Account
  alias Warehouse.Account.User

  @create_attrs %{email: "some email", firstname: "some firstname", lastname: "some lastname", password: "some password"}
  @update_attrs %{email: "some updated email", firstname: "some updated firstname", lastname: "some updated lastname", password: "some updated password"}
  @invalid_attrs %{email: nil, firstname: nil, lastname: nil, password: nil}

  def fixture(:user) do
    {:ok, user} = Account.create_user(@create_attrs)
    user
  end

  setup %{conn: conn} do
    # create user to be logged in
    {:ok, user} = Account.create_user(%{email: "gg@ex.com", real_password: "abc123", real_password_confirmation: "abc123"})

    # create token for session
    {:ok, jwt, _claims} = Account.authenticate(%{user: user, password: "abc123"})

    # add authorization header to the request
    conn = conn
    |> put_req_header("authorization", "Bearer: #{jwt}")
    |> put_req_header("accept", "application/json")

    {:ok, %{conn: conn, user: user}}
  end

  describe "index" do
    test "lists all users", %{conn: conn} do
      conn = get conn, user_path(conn, :index)
      assert json_response(conn, 200)["data"] == []
    end
  end
end

每次我运行测试时,我总是收到来自我的错误处理程序的错误 Authentication already send。
为了让我的测试通过,我缺少什么?

编辑:
这是输出:

1) 测试索引列出所有用户 (WarehouseWeb.UserControllerTest) test/warehouse_web/controllers/user_controller_test.exs:32
** (Plug.Conn.AlreadySentError) 响应已经发送
代码:conn = get conn, user_path(conn, :index )
stacktrace:
(plug) lib/plug/conn.ex:508: Plug.Conn.resp/3
(plug) lib/plug/conn.ex:495: Plug.Conn.send_resp/3
(guardian) lib/guardian/ plug/ensure_authenticated.ex:61:Guardian.Plug.EnsureAuthenticated.respond/1
(仓库)lib/warehouse_web/auth/auth_pipeline.ex:1:WarehouseWeb.Guardian.AuthPipeline.plug_builder_call/2
(仓库)lib/warehouse_web/router。例如:8:WarehouseWeb.Router.api_auth/2
(仓库)lib/warehouse_web/router.ex:1:WarehouseWeb.Router 中的匿名 fn/1。match_route /4
(phoenix) lib/phoenix/router.ex:273: Phoenix.Router。call /1
(仓库) lib/warehouse_web/endpoint.ex:1: WarehouseWeb.Endpoint.plug_builder_call/2
(仓库) lib/warehouse_web/endpoint.ex:1: WarehouseWeb.Endpoint.call/2
(phoenix) lib/phoenix/ test/conn_test.ex:224: Phoenix.ConnTest.dispatch/5
test/warehouse_web/controllers/user_controller_test.exs:33: (测试)

4

1 回答 1

2

你所有的代码看起来都和我的很相似,它确实可以工作。唯一的区别是您的测试身份验证...那里有一个额外的分号。

它应该是

put_req_header("authorization", "Bearer #{token}")

代替

put_req_header("authorization", "Bearer: #{token}")

希望有帮助。让我知道问题是否仍然存在

于 2018-01-04T10:49:36.883 回答