2013-02-01 18 views
11

tôi có một giải pháp đơn giản, tôi đã thực hiện bản thân mình với các đối tượng sau đây:Sử dụng mô hình xác thực riêng biệt với lập mưu on Rails

  • Tài khoản (đã lĩnh thẻ, được trả về khi chứng thực và được sử dụng trong các cuộc gọi API)
  • xác thực (có auth_type/auth_id và tham chiếu đến tài khoản)

tôi có một riêng biệt xác thực mô hình để có thể kết nối một số cách đăng nhập (thiết bị UUID, email/mật khẩu, twitter, facebook, vv). Nhưng có vẻ như trong tất cả các ví dụ về Devise bạn sử dụng nó trên mô hình Người dùng (Tài khoản).

Điều đó không linh hoạt hơn? Ví dụ: mô-đun OmniAuth lưu trữ nhà cung cấp và id trên mô hình Người dùng, điều gì sẽ xảy ra nếu bạn muốn có thể đăng nhập từ cả Twitter và Facebook, chỉ có một phòng cho một nhà cung cấp?

Tôi có nên sử dụng Devise trên mô hình Tài khoản hoặc Xác thực của mình không?

Trả lời

8

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.

+0

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

+0

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

1

Bạn có thể tách tất cả logic chung thành mô-đun và chỉ sử dụng cùng một bảng.

module UserMethods 
    #... 
end 

class User < ActiveRecord::Base 
    include UserMethods 
    devise ... 

end 

class Admin < ActiveRecord::Base 
    include UserMethods 
    self.table_name = "users" 
    devise ... 
end 

Và định cấu hình tất cả mô hình phát triển riêng rẽ trong các tuyến đường, chế độ xem (nếu cần, xem Định cấu hình chế độ xem). Trong trường hợp này, bạn có thể dễ dàng xử lý tất cả các logic khác nhau.

Cũng lưu ý rằng nếu bạn đang có niềm tin chỉ dành cho người dùng, thì bạn đã sai.

Ví dụ: - rails g devise Admin

Điều này sẽ tạo ra cho mô hình quản trị.

Thông tin thêm here.

+0

Rất tiếc, điều này không trả lời được câu hỏi, tôi không muốn thêm vai trò khác. Câu hỏi đặt ra là liệu có nên định cấu hình dựa trên mô hình người dùng thực tế (hay bất kỳ thứ gì, tôi đang sử dụng tài khoản) hoặc trên một đối tượng xác thực riêng biệt để làm cho nó linh hoạt hơn. – thejaz