Créez une authentification pouvant être liée à plusieurs SNS. Devise continuera comme implémenté. Nous ne parlerons pas de l'acquisition de chaque clé API, veuillez donc vérifier en conséquence. Cette fois, nous allons l'implémenter sur Facebook et Twitter, mais je pense que c'est fondamentalement la même chose pour les autres SNS.
environnement
Windows10
ruby 2.6.6
Rails 6.0.3.1
Gemfile
gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
Veuillez regrouper l'installation après l'enregistrement.
Pour Windows, veuillez vous reporter à Article précédent.
credentials.yml
facebook:
  api_key: pk_test_~
  secret_key: sk_test_~
twitter:
  api_key: pk_test_~
  secret_key: sk_test_~
Dans config / initializer.
devise.rb
#Ajoutez ce qui suit
config.omniauth :facebook, Rails.application.credentials.facebook[:api_key], Rails.application.credentials.facebook[:secret_key], scope: 'email', info_fields: 'email,name'
config.omniauth :twitter, Rails.application.credentials.twitter[:api_key], Rails.application.credentials.twitter[:secret_key], scope: 'email', callback_url: 'https://localhost:3000/users/auth/twitter/callback'
Il semble que Twitter ait besoin de spécifier l'URL de rappel.
Cette fois, on suppose que le modèle User a déjà été créé dans Devise. Vous pouvez ajouter des colonnes au modèle User, mais cette fois nous allons créer un nouveau modèle Social lié au modèle User. (Le modèle utilisateur et le modèle social ont une relation un-à-plusieurs.)
console
rails g model social
Le modèle social doit avoir user_id, provider (qui contient «facebook», «twitter», etc.) et uid (qui contient l'id à associer à chaque compte SNS).
2020~create_socials.rb
class CreateSocials < ActiveRecord::Migration[6.0]
  def change
    create_table :socials do |t|
      t.references :user, null: false, foreign_key: true
      t.string :provider, null: false
      t.string :uid, null: false
      t.timestamps
    end
  end
end
Après l'enregistrement, rails db: migrate.
user.rb
has_many :socials, dependent: :destroy#ajouter à
devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, 
          :omniauthable#ajouter à
social.rb
belongs_to :user
validates :uid, uniqueness: {scope: :provider}#Empêcher les enregistrements multiples chez le même fournisseur
Empêchez le même compte SNS d'être lié à plusieurs utilisateurs. Je pense que ce n'est pas grave si vous n'avez pas "{scope :: provider}", mais juste au cas où.
routes.rb
devise_for :users, controllers: {
  sessions: 'users/sessions',
  password: 'users/password',
  registrations: 'users/registrations',
  omniauth_callbacks: 'users/omniauth_callbacks'#ajouter à
  }
Ci-dessous dans app / controllers / users / omniauth_callbacks_controller.rb. (Vérifiez avec les itinéraires ferroviaires, etc. et définissez la méthode pour chaque destination de redirection.)
omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
 def facebook
    if request.env['omniauth.auth'].info.email.blank?#Autorisez-vous les e-mails sur Facebook?
      redirect_to '/users/auth/facebook?auth_type=rerequest&scope=email'
    end
    callback_from :facebook
  end
  def twitter
    callback_from :twitter
  end
  private
  def callback_from(provider)
    provider = provider.to_s
    if user_signed_in?
      @user = current_user
      User.attach_social(request.env['omniauth.auth'], @user.id)#Joindre plus tard_marque sociale. Transmettez les informations de SNS et l'identifiant de l'utilisateur connecté.
    else
      @user = User.find_omniauth(request.env['omniauth.auth'])#Trouver plus tard_Faites omniauth. Transmettez les informations de SNS.
    end
    if @user.persisted?#Enregistré ou si vous pouvez vous inscrire
      flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
      sign_in_and_redirect @user, event: :authentication
    else
      session["devise.#{provider}_data"] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end
Passez le type de SNS de la source de redirection à "callback_from" et isolez-le. Dans "callback_from", "l'enregistrement d'un nouvel utilisateur par authentification SNS ou connexion de l'utilisateur authentifié SNS" ou "Coopération SNS de l'utilisateur connecté" a été séparé. Les traitements «après enregistrement», «après connexion» et «après coopération» ne sont pas divisés cette fois, mais tous sont redirigés vers la page utilisateur.
Ensuite, écrivez chaque processus dans User.rb.
user.rb
 def self.find_omniauth(auth)#Nouvel enregistrement ou connexion SNS avec authentification SNS
    social = Social.where(uid: auth.uid, provider: auth.provider).first
    unless social.blank?#certifié sns(S'identifier)
      user = User.find(social.user.id)
    else#Nouvel enregistrement avec authentification SNS
      temp_pass = Devise.friendly_token[0,20]#Cette fois, je vais créer un mot de passe aléatoire pour le moment
      user = User.create!(
        username: auth.info.name,
        email: auth.info.email,
        password: temp_pass,
        password_confirmation: temp_pass,
      )
      social = Social.create!(
        user_id: user.id,
        provider: auth.provider,
        uid: auth.uid,
      )
    end
    return user
 end
 def self.attach_social(auth, user_id)#Lors de l'ajout d'une liaison sns
    social = Social.create!(
      user_id: user_id,
      provider: auth.provider,
      uid: auth.uid,
    )
  end
Au moment de «l'enregistrement d'un nouvel utilisateur par authentification SNS ou connexion d'un utilisateur authentifié SNS», il est en outre divisé en «nouvel enregistrement» et «connexion». Au moment de la "nouvelle inscription", l'utilisateur et le social sont créés (en même temps, l'utilisateur et le social sont liés), et l'utilisateur est renvoyé. Au moment de la "connexion", Social est recherché à partir des informations (auth.uid et auth.provider) envoyées par SNS, et l'utilisateur associé est renvoyé. Seul Social est créé au moment du "lien SNS de l'utilisateur connecté". Il reçoit user_id à associer à l'utilisateur connecté.
C'est la fin du processus. Après cela, si vous créez un lien avec "user_facebook_omniauth_authorize_path" etc., une nouvelle inscription, une nouvelle connexion et une coopération seront effectuées en fonction de la situation de l'utilisateur.
En fait, je pense qu'il serait préférable d'avoir un lien vers le SNS lié, un mécanisme de réinitialisation du mot de passe lors de la nouvelle inscription sur le SNS, l'authentification mail de Devise, un bouton pour annuler le lien, etc., mais pour le moment la configuration minimale vient de le faire. J'étudie les rails, donc je pense qu'il y a beaucoup d'endroits qui ne sont pas intelligents. Si vous faites quelque chose d'étrange, faites-le moi savoir!
Recommended Posts