Phoenix와 Expo가 제작한 스마트폰 애플리케이션 ②JWT인증+CRUD편
11899 단어 ElixirReact NativeExpophoenixtech
Phoenix와 Expo가 제작한 스마트폰 애플리케이션 ②JWT인증+CRUD편<-본문
저번elixir,phoenix 설정 및 프로젝트 만들기
phx-gen-auth를 사용하여 인증 기능을 가진 사용자를 만들었습니다
이번에는 Guardian을 이용해서 프론트 데스크와의 JWT 인증과 CRUD 기능을 실현하려고 합니다.
크루드 제작
이전 기사에서 User만 생성되었을 뿐 API 주위에 필요한 파일이 없기 때문에 우선 다음 명령을 사용하여 API 주위의 파일과 함께 CRUD를 생성합니다
mix phx.gen.json Posts Post posts body:string user_id:references:users
일반적인 응용 상황에서phx.은gen.}이지만 API의 경우 phx입니다.gen.json 사용사용자와 관련이 있기 때문에userusers로 외부 키와 관련자 설정
다음 관계 설정
[new] lib/sns/posts/post.ex
defmodule Sns.Posts.Post do
use Ecto.Schema
import Ecto.Changeset
schema "posts" do
field :body, :string
field :user_id, :id # <- こっちは消す
belongs_to :user, Sns.Users.User # <-こっちを書き加える
timestamps()
end
@doc false
def changeset(post, attrs) do
post
|> cast(attrs, [:body, :user_id]) # <- user_idを追加
|> validate_required([:body, :user_id]) # <- user_idを追加
end
end
[edit] lib/sns/users/user.exdefmodule Sns.Users.User do
use Ecto.Schema
import Ecto.Changeset
@derive {Inspect, except: [:password]}
schema "users" do
field :email, :string
field :password, :string, virtual: true
field :hashed_password, :string
field :confirmed_at, :naive_datetime
has_many :posts, Sns.Posts.Post # <- これを追加
timestamps()
end
...
end
경비를 설치하다.
Guardian 정보여기.
mix.exs에 다음mixdeps를 추가합니다.실행 get
[edit]mix.exs
defp deps do
[
...
{:guardian, "~> 2.0"}
]
end
다음 참조여기. 설정 Guardiansecret_키는 mix guardian입니다.gen.secret에서 만든 파일을 붙여넣거나 환경 변수를 설정하십시오
[edit]config/config.exs
config :sns, Sns.Guardian,
issuer: "sns",
secret_key: "Secret key. You can use `mix guardian.gen.secret` to get one"
[new]lib/sns/guardian.exdefmodule Sns.Guardian do
use Guardian, otp_app: :sns
# Guardian.encode_and_sign(sign_up/sign_in)で実行
def subject_for_token(user, _claims) do
sub = to_string(user.id)
{:ok, sub}
end
# headerのBearerのJWTを検証時(sign_up/sign_in以外のAPI)に実行
def resource_from_claims(claims) do
id = claims["sub"]
resource = Sns.Users.get_user!(id)
{:ok, resource}
end
end
README.md에subjectfor_token, resource_from_claims에도 오류가 있을 때 함수가 있지만,comple에서는 다음과 같은 경고가 나타나고, 오류가 있을 때 뒤에 설명된guardian의 error가 나타납니다.handler 및 fallbackcontroller가 처리하기 때문에 평상시 함수만 있습니다warning: this clause for resource_from_claims/1 cannot match because a previous clause at line 10 always matches
인증 기능의 구현(Model)
Guardian 설정이 완료되었으므로 인증 섹션 만들기
저번phx-gen-auth에서 웹 화면의 인증 부분을 만들었기 때문에 JWT도 이 부분을 사용하여 실현할 것이다
[edit]lib/sns/users.ex
defmodule Sns.Users do
...
alias Sns.Guardian
@doc """
Generates a JWT
"""
def token_sign_in(email, password) do
if user = get_user_by_email_and_password(email, password) do
Guardian.encode_and_sign(user)
else
{:error, :unauthorized}
end
end
...
end
인증 기능의 구현(Controller, View)
다음은 디렉터 및 뷰 생성
API와 같은 일반적인/appi/v1 폴더 구성은 controllers/appi/v1과 폴더를 만들고 생성된 파일의 모듈 이름을 Sns로 지정합니다.Api.V1.User Controller라면 괜찮습니다.
[new]lib/sns_web/api/v1/user_controller.ex
defmodule SnsWeb.Api.V1.UserController do
use SnsWeb, :controller
alias Sns.Users
alias Sns.Users.User
alias Sns.Guardian
action_fallback SnsWeb.FallbackController
def show(conn, _params) do
user = Guardian.Plug.current_resource(conn)
render(conn, "show.json", user: user)
end
def create(conn, %{"user" => user_params}) do
with {:ok, %User{} = user} <- Users.register_user(user_params) do
{:ok, token, _claims} = Guardian.encode_and_sign(user)
conn |> render("jwt.json", token: token)
end
end
def sign_in(conn, %{"email" => email, "password" => password}) do
with {:ok, token, _claims} <- Users.token_sign_in(email, password) do
conn |> render("jwt.json", token: token)
end
end
end
action_fallback 설정의 Fallback Controllercontroller에서 오류가 발생했을 때 대응하는 오류를 되돌려줍니다
이렇게 되면 하나하나 잘못 처리할 필요가 없다
그리고 이거랑 changeeset.view는 px입니다.아까 젠슨이 모형을 만들 때 같이 만들었어요.
뷰는 로그인과 새로 만들 때 돌아오는 JWT와 테스트용 쇼만 있기 때문에 필요에 따라 제작하세요
[new]lib/sns_web/views/api/v1/user_view.ex
defmodule SnsWeb.Api.V1.UserView do
use SnsWeb, :view
def render("show.json", %{user: user}) do
%{data: %{id: user.id, email: user.email}}
end
def render("jwt.json", %{token: token}) do
%{token: token}
end
end
인증 기능의 구현(Router)
마지막으로 러터 파트.
인증이 필요한 곳은 jwt앱을 통해
[edit]lib/sns_web/router.ex
Guardian의 설정으로 제작된 Guardian입니다.ex와guardian 오류를 처리하는 모듈을 설정합니다
[new]lib/sns_web/api_auth_pipeline.ex
defmodule SnsWeb.Router do
alias SnsWeb.ApiAuthPipeline
pipeline :jwt_authenticated do
plug ApiAuthPipeline
end
scope "/api/v1", SnsWeb do
pipe_through :api
post "/sign_up", Api.V1.UserController, :create
post "/sign_in", Api.V1.UserController, :sign_in
end
scope "/api/v1", SnsWeb do
pipe_through [:api, :jwt_authenticated]
get "/mypage", Api.V1.UserController, :show
resources "/posts", Api.V1.PostController, except: [:new, :edit]
end
end
설정 작업[new]lib/sns_web/api_auth_error_handler.ex
defmodule SnsWeb.ApiAuthPipeline do
use Guardian.Plug.Pipeline, otp_app: :sns,
module: Sns.Guardian,
error_handler: SnsWeb.ApiAuthErrorHandler
plug Guardian.Plug.VerifyHeader, realm: "Bearer"
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource
end
사용자 signup/signin 동작 확인
설치가 끝났습니다. 작업을 확인하십시오.
동작 확인 사용Postman
새로 만들기 실패 시
px-auth-gen의 초기 설정에서 비밀번호가 12글자를 초과하여 오류가 발생했습니다
새로 만들기 성공 시
성공, 영패 이미 반환
로그인 실패 시
로그인 성공 시
성공, 영패 이미 반환
토큰 인증은 Authorization 태그를 선택하고 type을 Bearer Token으로 설정하십시오.
jwt 인증 실패 시
jwt 인증 성공 시
Authorization의 Token에 로그인 성공 또는 새로 작성된 Token을 설정하십시오.
정상적인 응답과 오류를 확인했을 때의 응답이 모두 왔습니다
#CRUD 작업 확인
그 다음에 크루드도 동작 확인을 하고 그 전에 손발을 살짝 움직일 거예요.
Post 작성 시 user 사용id가 필요하지만 그것을 얻을 때
defmodule SnsWeb.ApiAuthErrorHandler do
import Plug.Conn
def auth_error(conn, {type, _reason}, _opts) do
body = Jason.encode!(%{error: to_string(type)})
send_resp(conn, 401, body)
end
end
귀찮아서 피플라인으로 처리id에서 얻기 위해서.[new] lib/sns_web/auth_helper.ex
alias Sns.Guardian
def create(conn, %{"post" => params})
post_params = Map.put(
params,
:user_id,
Guardian.Plug.current_resource(conn).id
)
....
end
[edit] lib/sns_web/router.exdefmodule SnsWeb.AuthHelper do
import Guardian.Plug
def init(opts), do: opts
def call(conn, _opts) do
Map.put(conn, :user_id, current_resource(conn).id)
end
end
[edit] lib/sns_web/controllers/api/v1/post_controller.exdefmodule SnsWeb.Router do
use SnsWeb, :router
alias SnsWeb.ApiAuthPipeline
alias SnsWeb.AuthHelper # <- これを追加
import SnsWeb.UserAuth
pipeline :jwt_authenticated do
plug ApiAuthPipeline
plug AuthHelper # <- これを追加
end
이렇게 하면 좀 가벼워요.이렇게 전체를 통해서 중간에 처리하고 싶을 때 pipeline에 넣으면 매끄러워요.
그럼 동작 확인을 해보도록 하겠습니다.
글을 쓰다
기사 목록
기사 편집
기사 삭제
204 no_콘텐츠가 돌아왔습니다.
CRUD 작동 확인
JWT 인증 + CRUD 편 이상 감사합니다.
다음에는 Post에 이미지를 첨부하여 파일 업로드 섹션을 작성합니다.
낙하점
Repo에서 user의 기록을 얻었지만 Guardian의 인증이 순조롭지 않을 때
IO.inspect(Guardian.encode_and_sign(user))
실행 중 다음 오류 발생
{:error, :secret_not_found}
원인은 config입니다.exs의 sercret키의 타자입니다.
otp_app, issuper, app 이름도 타자 실수하기 쉬운 부분이기 때문에 Guardian만 잘 안 될 때 타자 방식을 의심하세요.
이번 일
참조 페이지
Reference
이 문제에 관하여(Phoenix와 Expo가 제작한 스마트폰 애플리케이션 ②JWT인증+CRUD편), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/the_haigo/articles/143e03ecb833ecba3870텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)