Fügen Sie zuerst den Experten ein. pundit ist ein Juwel, das die Autorisierung verwaltet.
Was ist der Unterschied zwischen Authentifizierung und Autorisierung?
[Zertifizierung] ist wie das Zeigen eines Führerscheins. Es ist ein Prozess, um zu beweisen, wer du bist.
[Autorisierung] ist, welche Art von Auto Sie fahren können, was auf dem Führerschein angegeben ist. Abhängig von der Lizenz gibt es verschiedene Arten von Lizenzen, z. B. mittelgroße und große, die nur mit einem Moped verwendet werden können. Mit anderen Worten, selbst auf dem System wissen Sie, wer Sie sind, aber Sie müssen verwalten, dass dieser Prozess nicht zulässig ist.
Und wenn Sie nicht einfach mit devise (devise_token_auth) autorisieren können, können Sie dies. Die Verwendung eines Autorisierungsjuwels wie pundit hat jedoch viele Vorteile, z. B. die Möglichkeit, es in Dateien zu unterteilen, die nur die Autorisierungsverarbeitung übernehmen und verwalten. Wenn die Anwendung wächst, werden Sie den Vorteil spüren.
Lassen Sie uns jetzt in Experten setzen. Es entspricht dem Pandit-Dokument, wird jedoch wie folgt installiert und initialisiert.
Gemfile
+ gem “pundit”
$ bundle
app/controllers/v1/application_controller.rb
class ApplicationController < ActionController::Base
+ include Pundit
…
end
$ rails g pundit:install
Stoppen Sie nach der Installation die Schienen einmal und starten Sie sie neu.
Siehe auch: https://github.com/varvet/pundit#generator
$ rails g pundit:policy post
Bei der Ausführung werden eine Richtliniendatei und eine Spezifikationsdatei erstellt.
Stellen Sie sich nun das Verhalten einer typischen Bulletin-Board-Anwendung vor.
Es gibt drei Hauptdateien, die geändert werden müssen.
Darüber hinaus gibt es Dateien, die standardmäßig nur einmal geändert werden müssen.
Lassen Sie uns das Verhalten von pundit beim Ändern dieser 4 Dateien verstehen.
app/controllers/v1/posts_controller.rb
def index
posts = Post.includes(:user).order(created_at: :desc).limit(20)
+ authorize posts
render json: posts
end
def show
+ authorize @post
render json: @post
end
def create
+ authorize Post
post = current_v1_user.posts.new(post_params)
if post.save
…
def update
+ authorize @post
if @post.update(post_params)
…
def destroy
+ authorize @post
@post.destroy
…
Was Sie hier beachten sollten, ist, wo Sie die "Autorisierung" setzen. Ich werde es später in diesem Artikel erklären.
Diese Berechtigung {model} ruft die entsprechende Methode in post_policy.rb auf. Ich habe post_policy.rb noch nicht repariert, daher wird der Index der Superklasse application_policy.rb aufgerufen und angezeigt.
app/policy/application_policy.rb
def index?
false
end
index?
Ist falsch, nicht wahr?
Wenn der Rückgabewert der Methode, die "{action}?" Entspricht, wahr ist, ist dies zulässig, und wenn er falsch ist, wird er abgelehnt. Daher tritt ein Authentifizierungsfehler auf.
{"status":500,"error":"Internal Server Error","exception":"#\u003cNameError: undefined local variable or method `current_user' for #\u003cV1::PostsController:0x00000000036a49a8\u003e\nDid you mean? current_v1_user
Dieser Fehler ist ein ziemlicher Songwriter. Es gibt keine Variable oder Methode namens current_user Das ist der Fehler.
Tatsächlich ruft pundit standardmäßig die Methode current_user auf und übergibt sie in application_policy.rb und post_policy.rb an @ user
.
In dieser Testanwendung wird jedoch der Namespace von v1 abgeschnitten, sodass Sie "current_v1_user" anstelle von "current_user" aufrufen müssen.
Dies kann durch Überschreiben der Methode pundit_user
in application_controller.rb behoben werden.
app/controllers/application_controller.rb
class ApplicationController < ActionController::API
…
+ def pundit_user
+ current_v1_user
+ end
Jetzt, da "current_v1_user" in pundit anstelle von "current_user" aufgerufen wird, wird die vorherige "undefinierte lokale Variable oder Methode" current_user "aufgelöst. Schlagen Sie erneut auf Curl.
{"status":500,"error":"Internal Server Error","exception":"#\u003cPundit::NotAuthorizedError: not allowed to index? this Post::ActiveRecord_Relation
Es scheint, dass ein 500-Fehler zurückgegeben wird, wenn er nicht zulässig ist.
Wenn Sie keine Berechtigung haben, ist ein 403-Fehler angemessen. Daher scheint es sinnvoll, Pundit :: NotAuthorizedError
in application_controller.rb zu retten.
app/controllers/application_controller.rb
class ApplicationController < ActionController::API
include DeviseTokenAuth::Concerns::SetUserByToken
+ rescue_from Pundit::NotAuthorizedError, with: :render_403
…
+ def render_403
+ render status: 403, json: { message: "You don't have permission." }
+ end
…
Lass es uns erneut versuchen.
$ curl localhost:8080/v1/posts -i
HTTP/1.1 403 Forbidden
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache
X-Request-Id: e19d413c-89c9-4701-94c5-ece2b12560a9
X-Runtime: 0.003657
Transfer-Encoding: chunked
{"message":"You don't have permission."}
Der Antwortcode 403 und die Nachricht wurden ordnungsgemäß zurückgegeben.
Wenn Sie versuchen, den def-Index?
In app / policy / application_policy.rb
von false in true zu ändern, wird die Beitragsliste normal zurückgegeben.
Application_policy.rb ist jedoch eine Oberklasse. Lassen wir hier also im Prinzip alles falsch.
Bearbeiten Sie die geerbte Unterklasse post_policy.rb.
Ich werde zuerst den endgültigen Code schreiben.
app/policies/post_policy.rb
# frozen_string_literal: true
#
#Post-Policy-Klasse
#
class PostPolicy < ApplicationPolicy
def index?
true
end
def show?
true
end
def create?
@user.present?
end
def update?
@record.user == @user
end
def destroy?
@record.user == @user
end
#
# scope
#
class Scope < Scope
def resolve
scope.all
end
end
end
Dies sollte wie vorgesehen funktionieren. Ich werde den Test dieses Mal als letztes schreiben, weil ich dem Verständnis des Verhaltens von Experten Priorität einräumte. Denken Sie nun daran, wo Sie die Berechtigung in den Controller eingefügt haben.
app/controllers/v1/posts_controller.rb
def index
posts = Post.includes(:user).order(created_at: :desc).limit(20)
+ authorize posts
render json: posts
end
def show
+ authorize @post
render json: @post
end
def create
+ authorize Post
post = current_v1_user.posts.new(post_params)
if post.save
…
def update
+ authorize @post
if @post.update(post_params)
…
def destroy
+ authorize @post
@post.destroy
…
Beachten Sie, dass sie alle ** aufgerufen werden, bevor die Aktion ausgeführt werden muss **.
render json
ausrender json
ausif @ post.update (post_params)
aus@ post.destroy
ausEs wird sein. Was wäre, wenn Sie nach dem Speichern oder Aktualisieren "autorisieren" würden? Wenn Sie keine Berechtigung haben, wird die Antwort von 403 zurückgegeben. Da der Speichervorgang jedoch abgeschlossen ist, sollten Sie ihn in der Datenbank neu schreiben können. In diesem Fall macht eine Autorisierung keinen Sinn. Beachten Sie auch, dass die Autorisierung nur erfolgt, wenn Sie zuerst "autorisieren" aufrufen.
Unter dem Strich sollten Sie immer "authorize" aufrufen und sicherstellen, dass Sie wissen, wo Sie es aufrufen sollen.
Abschließend werde ich die Verarbeitung von "create?" Und "update?" Erklären.
app/policies/post_policy.rb
def create?
@user.present?
end
@ User
enthält current_v1_user
, aber wenn Sie sich nicht angemeldet haben, enthält @ user
nil.
Mit anderen Worten, die obige Methode gibt 200 für true zurück, wenn sie angemeldet ist, und 403 für false, wenn sie nicht angemeldet ist.
app/controllers/v1/post_controller.rb
def create
authorize Post
post = current_v1_user.posts.new(post_params)
Auch die Controllerseite achtet darauf. Beachten Sie, dass wir nicht "Post autorisieren" unter "post = current_v1_user.posts.new (post_params)" ausführen. Da "current_v1_user", wie oben erwähnt, null ist. Wenn Sie also versuchen, "authorize post" unter "post = current_v1_user.posts.new (post_params)" aufzurufen, existiert die posts-Methode nicht und Sie erhalten einen 500-Fehler.
Da für die Beurteilung nicht "Post", sondern "Benutzer" erforderlich ist, wird "Post" zusätzlich dazu übergeben, um die Autorisierung auszuführen.
Zweitens über das Verhalten von Updates? Und Schicksal?
app/policies/post_policy.rb
def update?
@record.user == @user
end
In diesem Fall wird der Aktualisierungs- / Löschzieldatensatz an "@ record" übergeben, da der Aktualisierungszieldatensatz in der Steuerung als "authorize @ post" übergeben wird. Vergleichen Sie den "Benutzer" dieses Datensatzes mit dem "@ Benutzer", an den der "aktuelle_v1_Benutzer" übergibt, und stellen Sie fest, ob sie übereinstimmen. Also ist es dein eigener Beitrag? Sie urteilen.
Im nächsten Artikel werde ich erklären, wie man Experten testet und wie man den Prozess in Methoden aufteilt.
→ Erstellen einer Bulletin Board-API mit Zertifizierung und Autorisierung in den Richtlinieneinstellungen von Rails 6 # 16 [Zur Serialisierungstabelle]
Recommended Posts