Phoenix - 与GuardianDb

时间:2017-05-03 22:50:26

标签: elixir phoenix-framework

在我的凤凰应用中,我使用GuardianGuardianDb进行用户授权。最初,我只使用Guardian,并且使用auth进程的一切工作都很好。然而,在将GuardianDb添加到混合(用于令牌存储)之后,令牌记录正在被正确创建,但是我收到了no case clause matching错误,这些错误让工作陷入困境,我似乎无法弄清楚如何获取周围。这就是它一切都在下降......

首先,来自mix.exs

{:guardian, "~> 0.14"},
{:guardian_db, "~> 0.8.0"},

以及文档中指定的config.exs

config :guardian, Guardian,
  hooks: GuardianDb,
  issuer: "MyApp",
  ttl: {30, :days},
  verify_issuer: true,
  serializer: MyApp.GuardianSerializer

config :guardian_db, GuardianDb,
  repo: MyApp.Repo,
  schema_name: "guardian_tokens"

create中的session_controller.ex操作期间出现错误:

def create(conn, %{"person" => person_params}) do
  case authenticate(person_params) do
    {:ok, person} ->
      new_conn = Guardian.Plug.api_sign_in(conn, person, :access)
      jwt = Guardian.Plug.current_token(new_conn)

      json new_conn, %{status: "ok", data: person, meta: %{token: jwt}}
    :error ->
      json(conn |> put_status(401), %{status: "error", message: "Invalid credentials"})
  end
end

当我尝试调用此操作时,在数据库中创建了所需的记录 - 但是,我收到以下错误(为整洁格式添加了反斜杠):

(CaseClauseError) no case clause matching:
{:ok, {%MyApp.Person{__meta__: #Ecto.Schema.Metadata<:loaded, "people">, \
deleted_at: nil, email: "user@test.com", first_name: "FirstName", \
id: "people:Jz3bIt54283NvZb", inserted_at: ~N[2017-05-01 18:02:17.750603], \
last_name: "LastName", password: nil, updated_at: ~N[2017-05-01 18:02:17.750612]}, \
:access, %{"aud" => "people:Jz3bIt54283NvZb", "exp" => 1496441175, \
"iat" => 1493849175, "iss" => "MyApp", \
"jti" => "248e62ed-a2a2-4a0a-9e08-eae0190516c6", "pem" => %{}, \
"sub" => "Person:people:Jz3bIt54283NvZb", "typ" => "access"}, \
"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJQZXJzb246cGVvcGxlOkp6M2JJdEpnTzU4M052WmIiLCJleHAiOjE0OTY0NDExNzUsImlhdCI6MTQ5Mzg0OTE3NSwiaXNzIjoiUGhvZW5peEJhY2tlbmQiLCJqdGkiOiIyNDhlNjJkZC1hMmEyLTRhMGEtOWYwOC1lYWUwMTkwNTE2YzYiLCJwZW0iOnt9LCJzdWIiOiJQZXJzb246cGVvcGxlOkp6M2JJdEpnTzU4M052WmIiLCJ0eXAiOiJhY2Nlc3MifQ.DliX044wFmKpCrawuH3W_DoCya2VYAdrxZfwWEGWtW_ymDxXmQgV6XL3bHRkPKhSHziaFQFMvHIGS9yKtBfTkg"}}

跟踪:

lib/guardian.ex:100: Guardian.encode_from_hooked/1
lib/guardian/plug.ex:178: Guardian.Plug.api_sign_in/4
(phoenix_backend) web/controllers/session_controller.ex:9: MyApp.SessionController.create/2

该跟踪的前两行来自依赖项,第三行引用上述控制器中的Guardian.Plug.api_sign_in(conn, person, :access)

在我添加GuardianDb之前,这个控制器动作工作得很好,但现在看来这个进程在依赖项中的一个钩子中被挂起,我不知道如何继续。

作为参考,跟踪中的第一行指向函数call_after_encode_and_sign_hook中的encode_from_hooked

defp encode_from_hooked({:ok, {resource, type, claims_from_hook}}) do
  {:ok, jwt} = encode_claims(claims_from_hook)
  case call_after_encode_and_sign_hook( # THIS IS LINE 100
    resource,
    type,
    claims_from_hook, jwt
  ) do
    :ok -> {:ok, jwt, claims_from_hook}
    {:error, reason} -> {:error, reason}
  end
end

并且跟踪中的第二行指向encode_and_sign函数中的api_sign_in

def api_sign_in(conn, object, type, new_claims) do
  the_key = Map.get(new_claims, :key, :default)
  new_claims = Map.delete(new_claims, :key)

  case Guardian.encode_and_sign(object, type, new_claims) do # THIS IS LINE 178
    {:ok, jwt, full_claims} ->
      conn
      |> set_current_resource(object, the_key)
      |> set_claims({:ok, full_claims}, the_key)
      |> set_current_token(jwt, the_key)
      |> Guardian.hooks_module.after_sign_in(the_key)

    {:error, reason} ->
      set_claims(conn, {:error, reason}, the_key)
  end
end

同样,我只想强调控制器动作在合并GuardianDb之前完美运行。现在我已经添加了GuardianDb,在数据库中正确创建了记录,但未正确定义new_conn

我知道这里有很多代码,但是我很难过 - 如果有人可以放弃一些光线,那就是muy bueno。

1 个答案:

答案 0 :(得分:0)

好吧我确实找到了一个解决方案,虽然我不愿意在我的应用程序中实现它,因为这是在一个dep ...

我所要做的就是调整:ok中的case encode_from_hooked子句,以便函数读取如下:

defp encode_from_hooked({:ok, {resource, type, claims_from_hook}}) do
  {:ok, jwt} = encode_claims(claims_from_hook)

  case call_after_encode_and_sign_hook(
    resource,
    type,
    claims_from_hook, jwt
  ) do
    {:ok, _} -> {:ok, jwt, claims_from_hook}
    :ok -> {:ok, jwt, claims_from_hook}
    {:error, reason} -> {:error, reason}
  end
end

在使用:ok返回元组时,只需要一个额外的案例。