[RUBY] Comment faire un contrôle basé sur l'API avec cancancan

Aperçu

Lors de la construction d'un système Web, je pense qu'il y a relativement beaucoup de demandes pour «gérer les autorisations pour chaque utilisateur».

Ruby on Rails vous permet de gérer les autorisations à l'aide d'un Gem appelé cancancan, qui gère les autorisations d'exécution (lecture / écriture) sur le modèle. L'utilisation de base est à faire.

Cette fois, il y a une exigence selon laquelle "je veux gérer l'autorité d'exécution de l'API", et j'ai cherché comment le faire, alors je l'ai résumé.

utilisation générale du cancancan (contrôle basé sur un modèle)

Avant d'entrer dans le sujet principal, je présenterai brièvement l'utilisation générale du cancancan (contrôle basé sur un modèle). (Presque une traduction japonaise du fichier Readme de Gem)

Installer Gem

Ajoutez ce qui suit à votre Gemfile.

gem 'cancancan'

Définition de la capacité

Les permissions accordées à un utilisateur sont définies dans la classe ʻAbility. Tout d'abord, créez la classe ʻAbility avec la commande suivante.

rails g cancan:ability

A titre d'exemple, contrôlez l'autorisation d'exécution du modèle Post.

class Ability
  include CanCan::Ability

  def initialize(user)
    can :read, Post, public: true  # public=Tout le monde peut voir le vrai record

    if user.present?  #Définir des autorisations utilisateur de connexion supplémentaires
      can :read, Post, user_id: user.id  # user_Vous pouvez également faire référence à des enregistrements dont l'ID est le vôtre

      if user.admin?  #Définir des autorisations supplémentaires pour l'utilisateur administrateur
        can :read, Post  #Tous les enregistrements peuvent être référencés
      end
    end
  end
end

cancancan a un wiki riche, et des méthodes de définition détaillées y sont également organisées. Defining Abilities - cancancan

Confirmation d'autorité

Lors de la vérification des autorisations dans une vue

<% if can? :read, @post %>
  <%= link_to "View", @post %>
<% end %>

Vous pouvez vérifier si l'utilisateur a l'autorisation de lecture pour la variable @ post avec can ?: read, @ post. Dans le cas de l'exemple ci-dessus, le lien ne s'affiche que lorsque vous avez l'autorisation de référence de @ post. Pour plus d'informations sur les helpers disponibles dans la vue, consultez les pages suivantes sur le wiki. Checking Abilities - cancancan

Lors de la vérification des autorisations sur le contrôleur

Comme condition préalable, la méthode utilisateur_actuel doit pouvoir référencer l'utilisateur connecté. Pré-installez des gemmes d'authentification telles que Devise et Authlogic.

def show
  @post = Post.find(params[:id])
  authorize! :read, @post  # current_utilisateur@Erreur si l'article ne peut pas être référencé
end

Si vous écrivez load_and_authorize_resource, before_action sera ajouté pour lire la ressource et vérifier l'autorité en fonction du nom du contrôleur. Vous pouvez utiliser load_and_authorize_resource pour éviter la situation où vous avez oublié d'écrire ʻauthorize!` Dans l'action que vous avez ajoutée plus tard et que vous avez raté le contrôle d'autorisation.

class PostsController < ApplicationController
  load_and_authorize_resource

  def show  # GET /posts/:post_Appelé lors de l'accès à l'identifiant
    # before_Faites ce qui suit en action
    # @post = Post.find(params[:post_id])
    # authorize! :show, @post
  end
end

Information supplémentaire

Les alias suivants sont coupés en interne dans cancancan.

alias_action :index, :show, :to => :read
alias_action :new, :to => :create
alias_action :edit, :to => :update

Ainsi, par exemple, ʻauthorize !: Show, @ post et ʻauthorize !: Read, @ post donneront le même résultat. cf. Action Aliases - cancancan

load_and_authorize_resource peut être divisé en load_resource et ʻauthorize_resource. Dans l'exemple ci-dessus, @post = Post.find (params [: post_id])une partie deload_resource est before_action, et ʻauthorize_resource est ʻauthorize !: Show, @ post fait partie de before_action. «Est ajouté. cf. Authorizing controller actions - cancancan

Contrôle basé sur l'API

C'est le sujet principal. Par exemple, supposons que vous ayez défini deux actions dans le contrôleur Post: show et ʻupdate`.

class PostsController < ApplicationController

  def show  # GET /posts/:post_API à appeler par identifiant
  end

  def update  # PUT /posts/:post_API à appeler par identifiant
  end
end

Permet à l'utilisateur administrateur d'exécuter à la fois GET / posts /: post_id et PUT / posts /: post_id, et aux autres utilisateurs d'exécuter uniquement GET / posts /: post_id.

Définition de la capacité

class Ability
  include CanCan::Ability

  def initialize(user)
    can :show, :post  # GET /posts/:post_id peut être exécuté par n'importe qui

    if user.admin?  #Définir des autorisations supplémentaires pour l'utilisateur administrateur
      can :update, :post  # PUT /posts/:post_L'identifiant ne peut être exécuté que par l'utilisateur administrateur
    end
  end
end

Confirmation d'autorité

Le but est de contrôler l'exécution de l'API, alors vérifiez auprès du contrôleur, pas de la vue.

class PostsController < ApplicationController

  authorize_resource class: false

  def show  # GET /posts/:post_API à exécuter sur id
    # before_Faites ce qui suit en action
    # authorize! :show, :post
  end

  def update  # PUT /posts/:post_API à exécuter sur id
    # before_Faites ce qui suit en action
    # authorize! :update, :post
  end
end

La clé est d'utiliser ʻauthorize_resource class: false au lieu de load_and_authorize_resource`.

ʻAuthorize_resource class: false` raison d'utiliser

Considérant le cas de show de PostsController comme exemple, ʻauthorize_resource semble ajouter before_action` qui fonctionne avec la logique suivante. (Je n'ai pas bien suivi la source, donc ça peut être exactement différent)

if @Une ressource est-elle affectée à la publication?
  authorize! :show, @post
elsif 'class: false'N'est-ce pas spécifié?
  authorize! :show, Post
else
  authorize! :show, :post
end

Si vous utilisez load_and_authorize_resource, la ressource sera placée dans @ post, donc la vérification des permissions de @ post sera exécutée. De plus, si vous ne spécifiez pas class: false, le modèle de vérification des autorisations de publication s'exécutera. C'est pourquoi nous utilisons ʻauthorize_resource class: false`.

en conclusion

J'ai cherché en ligne une méthode pour gérer l'autorisation d'exécution de l'API, mais je n'ai rien trouvé d'autre, alors je l'ai résumé cette fois. Si vous avez des erreurs, n'hésitez pas à commenter.

Je pense que ces exigences augmenteront avec la popularité des micro-services. Si vous vous trouvez dans une situation similaire, je vous serais reconnaissant de bien vouloir vous y référer.

Recommended Posts

Comment faire un contrôle basé sur l'API avec cancancan
Comment numéroter (nombre) avec html.erb
Comment mettre à jour avec activerecord-import
Comment démarrer avec Slim
Comment entourer n'importe quel caractère avec "~"
Comment utiliser mssql-tools avec Alpine
Comment démarrer Camunda avec Docker
Comment ajuster TextPosition avec l'extension de clavier iOS
Comment partager des fichiers avec Docker Toolbox
Comment compiler Java avec VsCode & Ant
[Java] Résumez comment comparer avec la méthode equals
[Android] Comment gérer les thèmes sombres
Comment utiliser BootStrap avec Play Framework
Comment changer d'images miniatures avec JavaScript
[Note] Comment démarrer avec Rspec
Comment faire une conversion de base en Java
Pour faire Stream.distinct avec les propriétés de champ, etc.
Comment réaliser le téléchargement de fichiers avec Feign
Comment mettre à jour les modèles associés avec accepte_nested_attributes_for
Comment définir JAVA_HOME avec l'appassembler-maven-plugin de Maven
Comment implémenter TextInputLayout avec la fonction de validation
Comment gérer les erreurs de connexion avec l'appareil
[Note] Comment utiliser Rails 6 Devise + cancancan
Comment supprimer des données avec une clé externe
Comment tester l'étendue privée avec JUnit
Comment surveiller nginx avec docker-compose avec datadog
Comment gérer les actifs de précompilation a échoué.
Comment réaliser le téléchargement de fichiers avec Feign
Comment exécuter Blazor (C #) avec Docker
Comment créer un environnement Rails 6 avec Docker
Comment télécharger Oracle JDK 8 rpm avec curl
[Java] Comment tester s'il est nul dans JUnit
Comment se moquer de chaque cas avec Mockito 1x
Comment utiliser MyBatis2 (iBatis) avec Spring Boot 1.4 (Spring 4)
Comment enregistrer dans plusieurs tables avec une seule entrée
Comment tester les interruptions pendant Thread.sleep avec JUnit
Comment utiliser h2db intégré avec Spring Boot
Comment utiliser le framework Java avec AWS Lambda! ??
Comment créer plusieurs menus déroulants avec ActiveHash
Comment utiliser le contrôle segmenté et les points à noter
Comment utiliser l'API Java avec des expressions lambda
Comment démarrer avec Eclipse Micro Profile
Comment donner votre image à quelqu'un avec Docker
Comment tout insérer en même temps avec MyBatis
Comment écrire du code de test avec la certification de base
Comment créer une API avec GraphQL et Rails
Comment utiliser le protocole NFS version 2 avec Ubuntu 18.04
Comment sortir un fichier de ressources avec spring-boot
Comment créer des variables membres avec le modèle JPA
Comment vérifier les éléments variables avec RequestBodyMatching de WireMock
[Rails] Comment créer un environnement avec Docker
Comment éviter les exceptions avec la méthode Equals de Java