[RUBY] Einführung des Experten Nr. 15 zum Erstellen einer Bulletin-Board-API mit Zertifizierung und Autorisierung in Rails 6

Erstellen einer Bulletin Board-API mit Zertifizierung und Autorisierung in Rails 6 # 14 Seed Execution Time Display

Unterschied zwischen Authentifizierung und Autorisierung

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.

Installiere pundit

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.

Machen Sie eine Post-Richtlinie

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.

Bearbeiten Sie 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 **.

Es 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.

Fortsetzung

Erstellen einer Bulletin Board-API mit Zertifizierung und Autorisierung in den Richtlinieneinstellungen von Rails 6 # 16 [Zur Serialisierungstabelle]

Recommended Posts

Einführung des Experten Nr. 15 zum Erstellen einer Bulletin-Board-API mit Zertifizierung und Autorisierung in Rails 6
Einführung von # 10 devise_token_auth zum Erstellen einer Bulletin Board-API mit Zertifizierung und Autorisierung in Rails 6
# 8 Seed-Implementierung zum Erstellen einer Bulletin Board-API mit Zertifizierungsautorisierung in Rails 6
Erstellen Sie eine Bulletin Board-API mit Zertifizierungsberechtigung in Rails 6 # 13 Grant-Authentifizierungsheader
Einführung des Serializers Nr. 9 zum Erstellen einer Bulletin-Board-API mit Zertifizierung und Autorisierung in Rails 6
Erstellen Sie eine Bulletin Board-API mit Zertifizierung und Autorisierung in Rails 6 # 6. Zeigen Sie, erstellen Sie die Implementierung
Erstellen Sie eine Bulletin Board-API mit Zertifizierung und Autorisierung im Rails 6 # 5-Controller und leiten Sie die Implementierung weiter
Erstellen Sie eine Bulletin Board-API mit Zertifizierung und Autorisierung in Rails 6 # 2 Einführung in Git und Rubocop
Erstellen Sie eine Bulletin Board-API mit Zertifizierung und Autorisierung in Rails 6 # 17. Fügen Sie Administratorrechte hinzu
Erstellen Sie eine Bulletin Board-API mit Zertifizierungsberechtigung im Rails 6 # 7-Update und zerstören Sie die Implementierung
Erstellen Sie eine Bulletin Board-API mit Zertifizierung und Autorisierung in Rails 6 # 14 Seed. Anzeige der Ausführungszeit
Erstellen Sie eine Bulletin-Board-API mit Zertifizierung und Autorisierung mit Rails 6 # 1 Environment Construction
Erstellen Sie eine Bulletin-Board-API mit Autorisierung in Rails 6 # 12 Assoziation von Benutzer und Beitrag
Erstellen Sie eine Bulletin-Board-API mit Autorisierung in Rails 6 # 11. Benutzermodelltest und Validierung hinzugefügt
Erstellen Sie mit Rails 6 # 18 eine Bulletin-Board-API mit Zertifizierung und Autorisierung. ・ Implementierung des Endbenutzer-Controllers
Erstellen Sie eine Bulletin Board-API mit Zertifizierung und Autorisierung mit Rails 6 # 3 RSpec. FactoryBot wird eingeführt und ein Post-Modell erstellt
# 4 nach Validierung und Testimplementierung zum Erstellen einer Bulletin Board-API mit Zertifizierung und Autorisierung in Rails 6
Ich habe versucht, mit Rails eine Gruppenfunktion (Bulletin Board) zu erstellen
Versuchen Sie, ein Bulletin Board in Java zu erstellen
So erstellen Sie eine API mit GraphQL und Rails
[So fügen Sie ein Video mit Rails in haml ein]
So richten Sie einen Proxy mit Authentifizierung in Feign ein
Einführung in React to Rails mit React-Rails
So benennen Sie ein Modell mit externen Schlüsseleinschränkungen in Rails um
Schritte zum Erstellen einer Ruby on Rails-Entwicklungsumgebung mit Vagrant
So fügen Sie ein Video in Rails ein
So erstellen Sie eine Ruby on Rails-Entwicklungsumgebung mit Docker (Rails 6.x)
So erstellen Sie eine Ruby on Rails-Entwicklungsumgebung mit Docker (Rails 5.x)
So erstellen Sie eine Rails 6-Umgebung mit Docker
So speichern Sie gleichzeitig Daten in einem Modell, das einem verschachtelten Formular zugeordnet ist (Rails 6.0.0)
Mit Rails in eine Tag-zu-URL-Zeichenfolge konvertieren
Erstellen Sie mit Java + MySQL ein einfaches Bulletin Board
[Rails] Rails neu, um eine Datenbank mit PostgreSQL zu erstellen
So implementieren Sie eine ähnliche Funktion in Rails
So erstellen Sie einfach ein Pulldown mit Rails
[Rails] So erstellen Sie eine Umgebung mit Docker
[Rails] [Docker] Kopieren und Einfügen ist in Ordnung! So erstellen Sie eine Rails-Entwicklungsumgebung mit Docker
Docker-Befehl zum Erstellen eines Rails-Projekts in einem einzigen Schlag in einer Umgebung ohne Ruby
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 1 (API Edition)
Umgang mit Fehlern in Rails s konnte keine JavaScript-Laufzeit finden.
Wirf Raw SQL mit Rails auf ein Lesereplikat
[Hinweis] Erstellen Sie eine Python3-Umgebung mit Docker in EC2
So schreiben Sie eine Datumsvergleichssuche in Rails
Ich möchte eine Funktion in der Rails Console definieren
Abfragen von Arrays in jsonb mit Rails + postgres
[Rails 6] So legen Sie ein Hintergrundbild in Rails [CSS] fest
Build Rails (API) x MySQL x Nuxt.js Umgebung mit Docker
[Rails] So laden Sie JavaScript in einer bestimmten Ansicht
Neuer Mitarbeiter hat versucht, mit Spring Security eine Authentifizierungs- / Autorisierungsfunktion von Grund auf neu zu erstellen
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 2 (Client Edition)
Einführung in Bootstrap in Rails 5
Bootstrap in Rails einführen !!