无法理解JWT auth(Phoenix)中的解构 [英] Can't understand destructuring in JWT auth (Phoenix)

查看:107
本文介绍了无法理解JWT auth(Phoenix)中的解构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设置一种模式,在Phoenix中使用Comeonin和Guardian进行JWT身份验证时,已经在API身份验证中看到了一些地方.

I'm setting up a pattern that I've seen a few places for API authentication in Phoenix, using Comeonin and Guardian for JWT auth.

当我从CURL发布到MyApp.SessionsController.create/2时,正如我期望的那样,我从MyApp.Session.authenticate/1返回了user响应.但是,我应该将其分解为{:ok, jwt, _full_claims},然后可以将其通过管道传递给Guardian.我使用IO.inspect user查看user对象并得到以下错误:

When I POST to MyApp.SessionsController.create/2 from CURL, I get a user response back from MyApp.Session.authenticate/1 as I would expect. However, I'm supposed to destructure it into {:ok, jwt, _full_claims}, which can then be piped to Guardian. I use IO.inspect user to look at the user object and get the following error:

端子:

curl -H "Content-Type: application/json" -X POST -d '{"email":"me@myapp.com","password":"password", "session":{"email":"mark@myapp.com", "password":"password"}}' http://localhost:4000/api/v1/sessions

当我在IEX中IO.inspect user时,我看到以下内容:

When I IO.inspect the user in IEX I see this:

%MyApp.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, avatar_url: nil,
 email: "me@myapp.com", handle: "me", id: 2,
 inserted_at: ~N[2017-08-22 18:26:10.000033], password: nil,
 password_hash: "$2b$12$LpJTWWEEUzrkkzu2w9sRheGHkh0YOgUIOkLluk05StlmTP6EiyPA6",
 updated_at: ~N[2017-08-22 18:26:10.007796]}

我看到这个错误:

Request: POST /api/v1/sessions
** (exit) an exception was raised:
    ** (MatchError) no match of right hand side value: %MyApp.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, avatar_url: nil, email: "me@myapp.com", handle: "mark", id: 2, inserted_at: ~N[2017-08-22 18:26:10.000033], password: nil, password_hash: "$2b$12$LpJTWWEEUzrkkzu2w9sRheGHkh0YOgUIOkLluk05StlmTP6EiyPA6", updated_at: ~N[2017-08-22 18:26:10.007796]}
        (myapp) web/controllers/api/v1/sessions_controller.ex:11: MyApp.SessionsController.create/2

这到底是什么意思:{:ok, jwt, _full_claims} = user?


这是设置:

What exactly does this mean: {:ok, jwt, _full_claims} = user?


Here's the setup:

# mix.exs
  defp deps do
    [
      {:distillery, "~> 1.4", runtime: false},
      {:phoenix, "~> 1.3.0-rc", override: true},
      {:phoenix_ecto, "~> 3.2"},
      ...
      {:comeonin, "~> 4.0"},
      {:bcrypt_elixir, "~> 0.12.0"},
      {:guardian, "~> 0.14.5"},
]


# web/router.ex
  ...
  pipeline :api do
    plug :accepts, ["json"]
    plug Guardian.Plug.VerifyHeader
  end

  scope "/api", MyApp do
    pipe_through :api

    scope "/v1" do
      post "/sessions", SessionsController, :create
    end
  end
...


# web/controllers/session_controller.ex
defmodule MyApp.SessionsController do  
  use MyApp.Web, :controller

  alias MyApp.{Repo, User}

  plug :scrub_params, "session" when action in [:create]

  def create(conn, %{"session" => session_params}) do
    case MyApp.Session.authenticate(session_params) do
    {:ok, user} ->
      {:ok, jwt, _full_claims} = user
        IO.inspect user       # Trying to test it here 
        |> Guardian.encode_and_sign(:token)
      conn
        |> put_status(:created)
        |> render("show.json", jwt: jwt, user: user)
    :error ->
      conn
      |> put_status(:unprocessable_entity)
      |> render("error.json")
    end
  end


# web/services/session.ex
defmodule MyApp.Session do 

  alias MyApp.{Repo, User}
  import Bcrypt

  def authenticate(%{"email" => email, "password" => password}) do
    case Repo.get_by(User, email: email) do
      nil -> 
        :error
      user ->
        case verify_password(password, user.password_hash) do
          true ->
            {:ok, user}
          _ ->
            :error
        end
    end
  end

  defp verify_password(password, pw_hash) do
    Comeonin.Bcrypt.checkpw(password, pw_hash)
  end
end


# lib/MyApp/User.ex
defmodule MyApp.User do
  use MyApp.Web, :model

  schema "users" do
    field :email, :string
    field :handle, :string
    field :password_hash, :string
    field :avatar_url, :string
    field :password, :string, virtual: true

    timestamps
  end

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, [:email, :handle, :password_hash, :password, :avatar_url])
    |> validate_required([:email])
    |> validate_length(:email, min: 1, max: 255)
    |> validate_format(:email, ~r/@/)
  end


添加监护人信息


Adding Guardian info

#config/config.exs
config :guardian, Guardian,
  issuer: "MyApp",
  ttl: { 30, :days},
  verify_issuer: true,
  secret_key: "abc123",
  serializer: MyApp.GuardianSerializer


#lib/MyApp/guardian_serializer.ex
defmodule MyApp.GuardianSerializer do
  @behaviour Guardian.Serializer
  alias MyApp.Repo
  alias MyApp.User

  def for_token(user = %User{}), do: {:ok, "User:#{user.id}"}
  def for_token(_), do: {:error, "Unknown resource type"}

  def from_token("User:" <> id), do: {:ok, Repo.get(User, id)}
  def from_token(_), do: {:error, "Unknown resource type"}
end

推荐答案

{:ok, jwt, _full_claims}是通过调用Guardian.encode_and_sign(user, :token)返回的值.这是您链接到的教程中的原始代码:

{:ok, jwt, _full_claims} is the value that's returned by calling Guardian.encode_and_sign(user, :token). This is the original code in the tutorial you linked to:

{:ok, jwt, _full_claims} = user 
  |> Guardian.encode_and_sign(:token)

与以下相同:

{:ok, jwt, _full_claims} = Guardian.encode_and_sign(user, :token)

另一方面,您的代码执行{:ok, jwt, _full_claims} = user,下一行是新语句.如果您想检查用户并仍然执行本教程的操作,则可以执行以下操作:

Your code on the other hand does {:ok, jwt, _full_claims} = user and the next line is a new statement. If you want to inspect the user and still do what the tutorial does, you can do:

{:ok, jwt, _full_claims} = user
  |> IO.inspect
  |> Guardian.encode_and_sign(:token)

IO.inspect返回打印后传递的值,因此该代码的功能与教程相同,除了它还将打印user的值.

IO.inspect returns the value that's passed after printing it, so this code will function identical to the tutorial except that it'll print the value of user as well.

这篇关于无法理解JWT auth(Phoenix)中的解构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆