可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
What is the best practice for combining Facebook login (let's say I'll use Omniauth gem) and email+password login?
I saw a few blogs, saw the Railscasts, I know everyone is using Devise gem with Omniauth. But I'm looking for some different perspective.
subquestions:
I'm considering creating email+password sign-up from scratch (not using any gem for this, lets keep it fast and light) so do you have any advice for this ? Or if you have particular gem in mind, please let it be fast.
And do you have any other recommendations for Oauth2 gems (alternative to Omniauth) handling authentication to Facebook ?
I'm sorry I'm asking this fundamental questions here, but I didn't found many answers (and most of them I found are based on Devise)
回答1:
This is how I saw it's done in most examples on the web
basicly when you signup with email+password, you are creating row directly to User model (not touching the Authent. model) and when signing up with Omniauth, than you are creating new authentication that communicates with User model.
And basicly on next login you are doing something like this :
if (user.password == 'xxx')
login
elsif user.authentication.uid == 'xxx'
login
else
'hello signup !'
end
so you are swiching between 2 models, and raping (sorry for the term) the User model witch should hold only user info
The solution, in a way, I think is correct (from my experience and discussions with my colleagues but I'm still not 100% sure this is the right answer)
as you see even the user+password is going trough Authent. model, that means the site user+password is acting as a provider on its own
so to be absolutly correct it should be look like this
signing up with FB: you save FB uid and authKey to authentication table, then create user
signing up with password: you create new row in AppPass table, then you create row in Authentication table (as a access to provider witch is actually your app) and than you create user
Why?
because now when user logs in, is always going trough Authent. model, not making condition between 2 models (the Authent. and the User model)
now can anyone please tell me, ...is this a good approach :D ?
回答2:
Intridea offers an email & password strategy to enable this:
https://github.com/intridea/omniauth-identity
:-)
回答3:
Omniauth is great, so you should probably use that for any/all social media logins.
As far as setting up your own authentication this shouldn't be too hard. Ryan Bates has a great screencast on this: Authentication from scratch
Here is a pretty good omniauth article (you will have to adapt it to your own users table though but its still a great resource) Omniauth rails rumble. Please note that I believe the article author uses the term authorization in the wrong context here. Omniauth has nothing to do with authorization, only authentication and this is a subtle but very important difference.
回答4:
Here's a link to the ruby toolbox page for the most popular authentication gems: http://ruby-toolbox.com/categories/rails_authentication.html. You probably aren't going to find the exact functionality you are looking for right out of the box with any of the solutions.
I don't think that you are correct that having the different authentication methods go to different tables will put too much strain (perhaps a better term) on the models.
It seems to me that if everyone is doing this using devise, there is a reason for it. You could probably get better performance by writing something scaled down yourself, but it's a big time investment. My guess is that the small performance improvement in your application is not going to be worth the time you spend writing something yourself.
If you're working on a current project with many thousands of concurrent users that is having difficulty scaling, please ignore my advice, since I am not familiar with those type of problems.
回答5:
I kinda dig in to these problematic more deeply an done some research on my own, these are the conclusions.
The problem is that I'm trying to combine my authentication functionality with site login/signup functionality, witch are two different behaviors. At the end of the FB signup with omniauth, you will have in your Authentication table the facebook uid and that is all that it takes to back login to FB for next time (of course you can store other info (like email) ... but logicly they are more users attributes and should go to user table).
note: its ok to store user information from provider, in Authentication table,
but if you want to work with them you should copy these informations to Users table
When you are signing up with email/password solution, you are writing information that define User on your site. (Authentication is just pointing to User) If we wanted to do password signup trough Authentication table, we would have to store the username & password inside authentications table, and this way merging User model and Authentication to one model. It will be much uglier solution, not talking about problem how to store multiple rows to one user. Also you the Authentication or Oauth are synonyms for "accessing your application trough other site" ( watch these oauth2 videos if you cannot imagine it http://www.youtube.com/view_play_list?p … 0139F609), yet with normal login you are accessing the site directly.
The only way around this problem is making a small app, that will handle the email/password or the user/password signup, generate password provider UID, and write those data to Users table, and than with our main applycation we will request trough omniauth to access the miniapp and store the UID in authentications table.
http://eq8scrapbook.heroku.com/equivalents_article/on_omniauth_and_password_login_best_practice