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