Gần đây, tôi đã làm việc trên một dự án mà tôi đang sử dụng Devise để giữ mã thông báo của người dùng cho các dịch vụ khác nhau. Một trường hợp khác đôi chút, nhưng câu hỏi của bạn vẫn khiến tôi suy nghĩ một lúc.
Tôi luôn ràng buộc Devise thành Tài khoản mô hình. Tại sao? Hãy xem.
Kể từ email của tôi là điều duy nhất có thể nhận ra tôi như một người dùng (và bạn tham khảo Tài khoản như User) Tôi sẽ đặt nó vào accounts
bảng trong cặp với mật khẩu, vì vậy mà tôi ban đầu có thể sử dụng xác thực email/mật khẩu cơ bản. Ngoài ra tôi sẽ giữ mã thông báo API trong authentications
.
Như bạn đã đề cập, mô-đun OmniAuth cần lưu trữ nhà cung cấp và id. Nếu bạn muốn người dùng của mình có thể kết nối với các dịch vụ khác nhau cùng một lúc (và vì một số lý do bạn làm) thì rõ ràng là bạn cần phải giữ cả hai cặp nhà cung cấp ở một nơi nào đó, nếu không sẽ chỉ được ghi đè mỗi lần một người dùng xác thực.Điều đó dẫn chúng tôi đến mô hình Xác thực đã phù hợp với điều đó và có tham chiếu đến Tài khoản.
Vì vậy, khi tìm kiếm cặp nhà cung cấp-id bạn muốn kiểm tra authentications
bảng chứ không phải accounts
. Nếu tìm thấy, bạn chỉ cần trả về một số account
được liên kết với nó. Nếu không thì bạn kiểm tra xem tài khoản có chứa email đó tồn tại hay không. Tạo mới authentication
nếu câu trả lời là có, nếu không hãy tạo một câu trả lời rồi tạo authentication
cho câu trả lời đó.
Để cụ thể hơn:
#callbacks_controller.rb
controller Callbacks < Devise::OmniauthCallbacksContoller
def omniauth_callback
auth = request.env['omniauth.auth']
authentication = Authentication.where(provider: auth.prodiver, uid: auth.uid).first
if authentication
@account = authentication.account
else
@account = Account.where(email: auth.info.email).first
if @account
@account.authentication.create(provider: auth.provider, uid: auth.uid,
token: auth.credentials[:token], secret: auth.credentials[:secret])
else
@account = Account.create(email: auth.info.email, password: Devise.friendly_token[0,20])
@account.authentication.create(provider: auth.provider, uid: auth.uid,
token: auth.credentials[:token], secret: auth.credentials[:secret])
end
end
sign_in_and_redirect @account, :event => :authentication
end
end
#authentication.rb
class Authentication < ActiveRecord::Base
attr_accessible :provider, :uid, :token, :secret, :account_id
belongs_to :account
end
#account.rb
class Account < ActiveRecord::Base
devise :database_authenticatable
attr_accessible :email, :password
has_many :authentications
end
#routes.rb
devise_for :accounts, controllers: { omniauth_callbacks: 'callbacks' }
devise_scope :accounts do
get 'auth/:provider/callback' => 'callbacks#omniauth_callback'
end
Điều đó sẽ cung cấp cho bạn những gì bạn cần trong khi vẫn giữ sự linh hoạt mà bạn muốn.
Cảm ơn bạn đã phản hồi! Tôi chỉ tự hỏi về mã thông báo; không phải mã thông báo cũng có trên Tài khoản không? Có lẽ tôi sẽ sử dụng chiến lược TokenAuthenticatable với chiến lược và nó thường được sử dụng trên mô hình Người dùng/Tài khoản thực tế? Có thể sử dụng các chiến lược mặc định trên mô hình Người dùng/Tài khoản nhưng TokenAuthenticatable trên một mô hình riêng biệt như Xác thực không? – thejaz
Không chắc chắn nếu có thể ra khỏi hộp, nhưng bạn luôn có thể ghi đè lên các phương thức từ DeviseSessionsController. Tôi chỉ muốn sử dụng cá nhân 'omniauthable'. – shrimpsushi