[RUBY] [Rails] Comment définir un mot de passe pour les messages, des mesures d'appel direct d'URL ont été prises

Comment définir un mot de passe pour un message

J'ai ajouté une fonction de mot de passe à l'article, j'ai donc écrit un article pour cette sortie.

Objectif de cet article

Vous pouvez définir le mot de passe comme indiqué dans l'image ci-dessous.

post_with_password.gif

Créer une fonction de publication

Créez une fonction de publication rapide. Si vous utilisez un échafaudage, vous pouvez le fabriquer en 1 minute.

$ rails new post_with_password $ cd post_with_password $ rails g scaffold Post description:text $ rails db:migrate

投稿機能.gif

Définir bcrypt

Le déroulement de la publication de l'utilisateur avec un mot de passe au saut en détail

  1. Définissez un mot de passe lors de la publication (messages / nouveaux)
  2. Demandez un mot de passe lors de l'ouverture de la page de détails (posts / show /: id) (s'il y a un mot de passe)
  3. Rediriger vers la page de détails si l'ID et le mot de passe correspondent

Utilisez bcrypt (gem) pour définir le mot de passe comme préparation préliminaire.

Le gem suivant est commenté dans le Gemfile, supprimez donc #. gem 'bcrypt', '~> 3.1.7'

$ bundle install

Ajoutez ensuite une phrase au modèle.

ruby:_form.html.erb


class Post < ApplicationRecord
  has_secure_password
end

$ rails g migration add_password_digest_to_posts password_digest:string $ rails db:migrate

Ajout de has_secure_password au modèle, En ajoutant la colonne password_digest Deux attributs seront disponibles: password et password_confirmation.

1. Définissez un mot de passe lors de la publication

Définissons le mot de passe pour le sujet principal.

Tout d'abord, laissez l'utilisateur définir un mot de passe dans la vue.

post.rb


(réduction)
  <div class="field">
    <%= form.label :description %>
    <%= form.text_area :description %>
  </div>
  
  <div class="field">
    <%= form.label :password %>
    <%= form.password_field :password %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

Ajoutez ensuite: mot de passe au paramètre strong.

posts_controller.rb


  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def post_params
      params.require(:post).permit(:description, :password)
    end
end

Vous pouvez maintenant enregistrer votre mot de passe dans db.

2. Demandez un mot de passe pour ouvrir la page de détails

La prochaine fois que vous accédez à la page de détails, demandez un mot de passe, et s'il correspond au mot de passe que vous avez défini, redirigez vers la page de détails.

Créez une page pour authentifier votre mot de passe.

ruby:posts_with_password.html.erb


<div class="users-new-wrapper">
  <div class="container">
    <div class="row">
      <div class="col-md-offset-4 col-md-4 users-new-container">
        <h1 class="text-center text-white">password</h1>
        <%= form_for(:post, {controller: 'posts', action: "posts_with_password/#{@post}" }) do |f| %>
          <div class="form-group">
            <%= f.label :password %>
            <%= f.password_field :password, class: 'form-control' %>
          </div>
            <%= f.submit "Envoyer", class: 'btn-block' %>
        <% end %>
      </div>
    </div>
  </div>
</div>

Ajoutez également le routage.

qiita.rb


Rails.application.routes.draw do
  resources :posts
  get       'posts_with_password/:id', to: 'posts#posts_with_password'
  post      'posts_with_password/:id', to: 'posts#authenticate'
end

Rediriger vers la page de détail si le mot de passe correspond

Enfin, créez la fonction d'authentification.

posts_controller.rb


(réduction)
 def authenticate
    post_id = Post.find(params[:id])
    if post_id && post_id.authenticate(params[:post][:password])
      redirect_to post_path(post_id)
    else
      render 'posts_with_password'
    end
  end

  def posts_with_pass

Si le message et le mot de passe correspondent, vous serez maintenant redirigé vers la page de détails.

C'est tout pour hier.

Cependant, dans ce cas, il est nécessaire de définir un mot de passe pour toutes les publications, la définition du mot de passe est donc facultative.

Puisque le has_secure_password défini par bcrypt sera retourné pour les messages vides, Ajoutez ce qui suit pour pouvoir publier même s'il est vide.

post.rb


class Post < ApplicationRecord
  has_secure_password(validations: false)
end

Lorsque passwaord_digest contient un mot de passe et quand il ne le fait pas Modifiez la destination du lien de la page de détails.

ruby:index.hetml.erb


(réduction)
<% @posts.each do |post| %>
  <tr>
    <td><%= post.description %></td>
    <td><%= link_to 'Show', post_path(post) %></td>
    <td><%= link_to 'Edit', edit_post_path(post) %></td>
    <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>

Cependant, avec cela, même si vous définissez un mot de passe, vous pouvez voir la description à partir de l'index.

スクリーンショット 2020-07-13 14.02.37.jpeg

Modifiez l'affichage de Description en fonction de la présence ou de l'absence de password_digest.

ruby:index.hetml.erb


<% @posts.each do |post| %>
  <tr>
    <% if post.password_digest.nil? %>
      <td><%= post.description %></td>
    <% else %>
      <td>secret</td>
    <% end %>
    <td><%= link_to 'Show', post_path(post) %></td>
    <td><%= link_to 'Edit', edit_post_path(post) %></td>
    <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>

Si password_digest est vide, il sera affiché comme d'habitude, et s'il n'est pas vide, il sera affiché comme "secret".

Accès restreint

Enfin, l'accès est restreint et il est terminé.

Si vous n'avez pas de mot de passe lorsque vous cliquez sur afficher, configurez-le pour accéder à la page de détails et si vous avez un mot de passe, vous serez redirigé vers le formulaire de saisie du mot de passe.

Cela résout également le problème que le mot de passe peut être brisé en entrant directement l'url.

Le mécanisme est le suivant.

  1. Vérifiez s'il existe un mot de passe pour les messages / show /: id

  2. S'il n'y a pas de mot de passe, posts / show /: id sera affiché tel quel

  3. S'il y a un mot de passe, redirigez vers posts / show /: id si l'url contient la valeur de password_digest Si non inclus, redirigez vers le formulaire de saisie du mot de passe

  4. L'explication doit être expliquée. Si vous n'avez pas de mot de passe, vous pouvez taper directement l'url pour afficher la page de détails, et il n'y a pas de problème. Le problème est que si vous tapez directement l'url dans un message avec un mot de passe, la page de détails sera affichée.

Pour le moment, "Redirigeons les publications avec des mots de passe vers le formulaire de saisie de mot de passe avec restrictions d'accès" Je suis accro à la pensée en court-circuit. (J'en étais accro)

Vous ne pourrez pas ouvrir la page de détails pour le reste de votre vie en utilisant la méthode ci-dessus. En effet, la page de détails a un mot de passe, que vous vous authentifiiez ou non à l'aide du formulaire de saisie de mot de passe.

Mon idée était d'envoyer les paramètres à redirect_to lorsque le mot de passe a été authentifié avec succès. Si l'url contient ce paramètre, c'est un moyen d'afficher la page de détails.

Vous pouvez également envoyer des paramètres à redirect_to. Cette fois, j'enverrai password_digest.

Il y a deux raisons.

  1. Parce qu'il est facile de retirer
  2. Parce qu'il est hautement sûr

J'ai pensé à envoyer des caractères alphanumériques aléatoires dans les paramètres à chaque fois, mais j'ai abandonné car c'était gênant de les supprimer.

En outre, il est hautement sécurisé si password_digest est inclus dans l'url, mais il peut être percé. Les valeurs sont de 60 chiffres en haut et en bas, des nombres et des symboles, donc cela peut être assez difficile.

Je suis désolé de l'expliquer pendant longtemps, mais j'écrirai le code du prochain.

Tout d'abord, définissez le paramètre sur redirect_to.

posts_controller.rb


def authenticate
    post_id = Post.find(params[:id])
    if post_id && post_id.authenticate(params[:post][:password])
ici-> redirect_to post_path(post_id, parameter: post_id.password_digest)
    else
      render 'index'
    end
  end

Après l'authentification par mot de passe, des paramètres seront ajoutés et l'URL changera.

Ensuite, l'accès est limité par la présence ou l'absence d'un mot de passe.

posts_controller.rb


before_action :with_password, only: :show

(réduction)
private
  def with_password
    url = request.url.gsub!(/%21|%22|%23|%24|%24|%25|%26|%27|%28|%29|%2A|%2B|%2C|%2F|%3A|%3B|%3C|%3D|%3E|%3F|%40|%5B|%5D|%5E|%60|%7B|%7C|%7D|%7E|/,
    "%21" => "!", "%22" => '"', "%23" => "#", "%24" => "$", "%25" => "%", "%26" => "&", "%27" => "'", "%28" => "(", "%29" => ")",
    "%2A" => "*", "%2B" => "+", "%2C" => ",", "%2F" => "/", "%3A" => ":", "%3B" => ";", "%3C" => "<", "%3D" => "=", "%3E" => ">", "%3F" => "?", "%40" => "@",
    "%5B" => "[", "%5D" => "]", "%5E" => "^", "%60" => "`", "%7B" => "{", "%7C" => "|", "%7D" => "}", "%7E" => "~")
    @post = Post.find(params[:id])
    if [email protected]_digest.nil? && !url.try(:include?, @post.password_digest)
      redirect_to "/posts_with_password/#{@post.id}", danger: 's'il vous plait entrez votre mot de passe'
    end
  end

Je vais expliquer dans l'ordre du haut. url = request.url Obtenez d'abord l'URL avec le code ci-dessus.

Je suis devenu accro ici quand j'écrivais le code. Même si j'ai obtenu l'URL telle quelle, elle n'a pas été authentifiée.

Lorsque vous comparez le contenu de url et password_digest à l'aide de byebug, certains caractères tels que $ sont C'était différent. Quand je l'ai recherché, il semblait y avoir des chaînes qui ne pouvaient pas être utilisées dans l'url, donc j'ai dû les encoder.

Je n'ai pas trouvé de moyen de le convertir en une seule fois, alors je l'ai changé de force en utilisant gsub. (S'il existe une autre bonne façon de l'écrire, merci de me le faire savoir.)

J'ai évoqué les informations suivantes. https://www.seil.jp/doc/index.html#tool/url-encode.html

Ceci termine l'acquisition de l'url.

Ceci est la finition finale. Le code suivant est expliqué et il est terminé.

if [email protected]_digest.nil? && !url.try(:include?, @post.password_digest)

Si vous essayez d'ouvrir la page de détails avec un mot de passe et que l'URL ne contient pas password_digest Redirigez vers le formulaire de saisie du mot de passe.

Si vous n'utilisez pas try, une erreur se produira si vous n'avez pas de mot de passe.

Résumé

C'est tout.

Veuillez utiliser bcrypt autre que la connexion.

J'espère que cela sera utile pour votre portfolio.

Recommended Posts

[Rails] Comment définir un mot de passe pour les messages, des mesures d'appel direct d'URL ont été prises
[Rails 6] Comment définir une image d'arrière-plan dans Rails [CSS]
Mesures pour prendre beaucoup de temps pour charger les images (Rails)
[Docker] Comment créer un environnement virtuel pour les applications Rails et Nuxt.js
Comment insérer une vidéo dans Rails
Comment créer un référentiel Maven pour 2020
[rails] Comment créer un modèle partiel
Nécessaire pour iOS 14? Comment définir NSUserTrackingUsageDescription
Rails: comment bien écrire une tâche de râteau
Comment créer une base de données H2 n'importe où
Convertir en balise dans la chaîne d'URL avec Rails
[Rails] Comment écrire lors de la création d'une sous-requête
[Rails] Comment créer un graphique à l'aide de lazy_high_charts
Comment créer des pages pour le tableau "kaminari"
[Rails] Comment implémenter un test unitaire d'un modèle
Comment créer un JRE léger pour la distribution
[Java] (pour MacOS) Méthode de définition du chemin de classe
Comment implémenter une fonctionnalité similaire dans Rails
Comment créer facilement un pull-down avec des rails
[Rails] Comment créer un bouton de partage Twitter
[Ruby on Rails] Comment implémenter la fonction de balisage / recherche incrémentielle pour les articles (sans gemme)