我刚刚完成了Michael Hartl教程.我正在尝试实施omniauth-facebook注册和登录用户.我在创建要create
在会话控制器中的操作中使用的主变量时遇到问题.我的假设是我应该if else
发表声明,看看主人是通过Facebook登录还是通过默认表格?或者我应该使用and or
声明:
(master = Master.find_by(email: params[:session][:email].downcase) || Master.from_omniauth(env["omniauth.auth"])) ?
这是omniauth-facebook sessons控制器创建动作代码:
def create user = User.from_omniauth(env["omniauth.auth"]) session[:user_id] = user.id redirect_to root_url end
这是我当前的会话控制器创建动作代码:
class SessionsController < ApplicationController def new end def create master = Master.find_by(email: params[:session][:email].downcase) if master && master.authenticate(params[:session][:password]) sign_in master redirect_back_or master else flash.now[:error] = 'Invalid email/password combination' render 'new' end end . . . end
Timur Mamedo.. 5
虽然我可能迟到一年才能回答这个问题,但我仍然认为像一年前那样出现类似问题的新观众可能会受益于以下答案
据我了解,实际问题是:
如何将Facebook身份验证与从Scratch构建的身份验证系统集成?
既然你说过你使用过迈克尔·哈特尔的教程,我就继续调整了迈克尔自己编写的认证系统的答案.现在让我们一步一步地遍历每一段代码.
首先,我们需要为现有的Users表创建两个额外的列,用于提供者和uid,如下所示......
rails g migration add_facebook_auth_to_users provider uid
...并在Gemfile中添加omniauth-facebook gem ...
的Gemfile
gem 'omniauth-facebook', '2.0.1'
不要忘记之后运行bundle install
和迁移数据库.
接下来我们需要继续编辑我们的Sessions控制器......
sessions_controller.rb
def create user = User.find_by(email: params[:session][:email].downcase) if user && user.authenticate(params[:session][:password]) if user.activated? log_in user params[:session][:remember_me] == '1' ? remember(user) : forget(user) redirect_back_or user else message = "Account not activated. " message += "Check your email for the activation link." flash[:warning] = message redirect_to root_url end else flash.now[:danger] = 'Invalid email/password combination' render 'new' end end def create_facebook user = User.from_omniauth(env["omniauth.auth"]) log_in user redirect_back_or user end
上面的会话控制器包含两个创建操作.第一个是直接从书中获取的未触及的方法,第二个是我专门用于Facebook身份验证的一段代码.
线user = User.from_omniauth(env["omniauth.auth"])
有两个目的.创建用户如果他/她的唯一facebook uid不在数据库ELSE中,如果uid存在,则在应用程序中记录此人.稍后会详细介绍.
接下来让我们创建一个有效的.from_omniauth方法,您可以在问题中简要地显示代码内部...
user.rb
def self.from_omniauth(auth) where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user| user.provider = auth.provider user.uid = auth.uid user.name = auth.info.name unless user.name != nil user.email = SecureRandom.hex + '@example.com' unless user.email != nil user.activated = true user.password = SecureRandom.urlsafe_base64 unless user.password != nil user.save! end end
在这里,我们试图找到匹配给定用户provider
,并uid
从哈希值,然后我们呼吁first_or_initialize
对这样的结果.此方法将返回第一个匹配记录或使用传入的参数初始化新记录.然后,我们调用tap
此方法将该User实例传递给块.在块内部,我们根据OmniAuth哈希值设置用户的各种属性.
您可能会对为什么unless
在一些属性初始化之后放置语句感兴趣.请考虑用户想要更新配置文件的情况,例如更改名称或smth,然后注销.当该用户最终决定重新登录时,该.from_omniauth
方法将覆盖用户有问题的更新到原始的facebook值,除非我们阻止它这样做.
另请注意SecureRandom
库的使用.在Michael Hartl在他的书中使用的传统身份验证中,他介绍了对电子邮件和密码提交的验证.电子邮件既不是空白也不是空白.同样,密码长度必须大于6个字符.由于电子邮件必须存在且独特,我决定使用电子邮件创建虚拟电子邮件SecureRandom.hex + @example.com
.这将创建一个随机的十六进制字符串,52750b30ffbc7de3b362
并将其追加@example.com
,从而生成唯一的虚拟电子邮件.密码相同,但我更喜欢使用生成随机base64字符串SecureRandom.urlsafe_base64
.最重要的是要记住Facebook用户不需要知道这些信息才能登录,因为这是使用Facebook身份验证的重点.这使他们可以在以后根据实际数据添加此信息.
现在是在主应用程序页面上添加按钮的好时机,供用户让他们实际登录到应用程序...
_header.html.erb
<% if logged_in? %> . . . <% else %> . .
那么,现在我们可以向facebook发送请求了.一个问题仍然是我们无法实际处理回调.为此,我们需要做以下事情......
添加get 'auth/:provider/callback' => 'sessions#create_facebook'
到routes.rb文件
使用Facebook提供的方便的Javascript SDK.让我们创建一个使用此SDK的自定义javascript文件...
应用程序/资产/ JavaScript的/ facebook.js.erb
jQuery(function() { $('body').prepend(''); return $.ajax({ url: window.location.protocol + "//connect.facebook.net/en_US/sdk.js", dataType: 'script', cache: true }); }); window.fbAsyncInit = function() { FB.init({ appId: 'your_facebook_app_id_goes_here', version: 'v2.3', cookie: true }); $('#sign_in').click(function(e) { e.preventDefault(); return FB.login(function(response) { if (response.authResponse) { return window.location = '/auth/facebook/callback'; } }); }); return $('#sign_out').click(function(e) { FB.getLoginStatus(function(response) { if (response.authResponse) { return FB.logout(); } }); return true; }); };
就是这样,除了一个小小的警告......
如果用户决定去编辑个人资料,他/她会看到我们的虚拟电子邮件显示在中间.这发生了,因为Rails足够聪明,可以自动填充用户的信息.在这种情况下,坦率地说,这非常令人尴尬.但是,好的方面是它很容易解决.只需在表单中将值设置为nil,就像这样......
<%= f.email_field :email, value: nil, class: 'form-control' %>
希望这有助于那些想从头开始构建身份验证系统的人:)
虽然我可能迟到一年才能回答这个问题,但我仍然认为像一年前那样出现类似问题的新观众可能会受益于以下答案
据我了解,实际问题是:
如何将Facebook身份验证与从Scratch构建的身份验证系统集成?
既然你说过你使用过迈克尔·哈特尔的教程,我就继续调整了迈克尔自己编写的认证系统的答案.现在让我们一步一步地遍历每一段代码.
首先,我们需要为现有的Users表创建两个额外的列,用于提供者和uid,如下所示......
rails g migration add_facebook_auth_to_users provider uid
...并在Gemfile中添加omniauth-facebook gem ...
的Gemfile
gem 'omniauth-facebook', '2.0.1'
不要忘记之后运行bundle install
和迁移数据库.
接下来我们需要继续编辑我们的Sessions控制器......
sessions_controller.rb
def create user = User.find_by(email: params[:session][:email].downcase) if user && user.authenticate(params[:session][:password]) if user.activated? log_in user params[:session][:remember_me] == '1' ? remember(user) : forget(user) redirect_back_or user else message = "Account not activated. " message += "Check your email for the activation link." flash[:warning] = message redirect_to root_url end else flash.now[:danger] = 'Invalid email/password combination' render 'new' end end def create_facebook user = User.from_omniauth(env["omniauth.auth"]) log_in user redirect_back_or user end
上面的会话控制器包含两个创建操作.第一个是直接从书中获取的未触及的方法,第二个是我专门用于Facebook身份验证的一段代码.
线user = User.from_omniauth(env["omniauth.auth"])
有两个目的.创建用户如果他/她的唯一facebook uid不在数据库ELSE中,如果uid存在,则在应用程序中记录此人.稍后会详细介绍.
接下来让我们创建一个有效的.from_omniauth方法,您可以在问题中简要地显示代码内部...
user.rb
def self.from_omniauth(auth) where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user| user.provider = auth.provider user.uid = auth.uid user.name = auth.info.name unless user.name != nil user.email = SecureRandom.hex + '@example.com' unless user.email != nil user.activated = true user.password = SecureRandom.urlsafe_base64 unless user.password != nil user.save! end end
在这里,我们试图找到匹配给定用户provider
,并uid
从哈希值,然后我们呼吁first_or_initialize
对这样的结果.此方法将返回第一个匹配记录或使用传入的参数初始化新记录.然后,我们调用tap
此方法将该User实例传递给块.在块内部,我们根据OmniAuth哈希值设置用户的各种属性.
您可能会对为什么unless
在一些属性初始化之后放置语句感兴趣.请考虑用户想要更新配置文件的情况,例如更改名称或smth,然后注销.当该用户最终决定重新登录时,该.from_omniauth
方法将覆盖用户有问题的更新到原始的facebook值,除非我们阻止它这样做.
另请注意SecureRandom
库的使用.在Michael Hartl在他的书中使用的传统身份验证中,他介绍了对电子邮件和密码提交的验证.电子邮件既不是空白也不是空白.同样,密码长度必须大于6个字符.由于电子邮件必须存在且独特,我决定使用电子邮件创建虚拟电子邮件SecureRandom.hex + @example.com
.这将创建一个随机的十六进制字符串,52750b30ffbc7de3b362
并将其追加@example.com
,从而生成唯一的虚拟电子邮件.密码相同,但我更喜欢使用生成随机base64字符串SecureRandom.urlsafe_base64
.最重要的是要记住Facebook用户不需要知道这些信息才能登录,因为这是使用Facebook身份验证的重点.这使他们可以在以后根据实际数据添加此信息.
现在是在主应用程序页面上添加按钮的好时机,供用户让他们实际登录到应用程序...
_header.html.erb
<% if logged_in? %> . . . <% else %> . . <li><%= link_to "Sign in with Facebook", "/auth/facebook", id: "sign_in" %></li> <% end %>
那么,现在我们可以向facebook发送请求了.一个问题仍然是我们无法实际处理回调.为此,我们需要做以下事情......
添加get 'auth/:provider/callback' => 'sessions#create_facebook'
到routes.rb文件
使用Facebook提供的方便的Javascript SDK.让我们创建一个使用此SDK的自定义javascript文件...
应用程序/资产/ JavaScript的/ facebook.js.erb
jQuery(function() { $('body').prepend('<div id="fb-root"></div>'); return $.ajax({ url: window.location.protocol + "//connect.facebook.net/en_US/sdk.js", dataType: 'script', cache: true }); }); window.fbAsyncInit = function() { FB.init({ appId: 'your_facebook_app_id_goes_here', version: 'v2.3', cookie: true }); $('#sign_in').click(function(e) { e.preventDefault(); return FB.login(function(response) { if (response.authResponse) { return window.location = '/auth/facebook/callback'; } }); }); return $('#sign_out').click(function(e) { FB.getLoginStatus(function(response) { if (response.authResponse) { return FB.logout(); } }); return true; }); };
就是这样,除了一个小小的警告......
如果用户决定去编辑个人资料,他/她会看到我们的虚拟电子邮件显示在中间.这发生了,因为Rails足够聪明,可以自动填充用户的信息.在这种情况下,坦率地说,这非常令人尴尬.但是,好的方面是它很容易解决.只需在表单中将值设置为nil,就像这样......
<%= f.email_field :email, value: nil, class: 'form-control' %>
希望这有助于那些想从头开始构建身份验证系统的人:)