Ruby on rails 使用curl连接到轨道会产生错误的响应
我已经实现了Matteo Melanis伟大的博客文章。它与Chrome扩展完美配合。然而,当我尝试使用cUrl获取用户身份验证令牌时,我遇到了一个奇怪的问题 首先,使用Postman获取(成功)身份验证的development.log条目:Ruby on rails 使用curl连接到轨道会产生错误的响应,ruby-on-rails,api,curl,devise,ruby-on-rails-4,Ruby On Rails,Api,Curl,Devise,Ruby On Rails 4,我已经实现了Matteo Melanis伟大的博客文章。它与Chrome扩展完美配合。然而,当我尝试使用cUrl获取用户身份验证令牌时,我遇到了一个奇怪的问题 首先,使用Postman获取(成功)身份验证的development.log条目: Started POST "/api/v1/tokens.json?email=my@mail.com&password=[FILTERED]" for 127.0.0.1 at 2013-11-25 11:28:21 +0100 Processi
Started POST "/api/v1/tokens.json?email=my@mail.com&password=[FILTERED]" for 127.0.0.1 at 2013-11-25 11:28:21 +0100
Processing by Api::V1::TokensController#create as JSON
Parameters: {"email"=>"my@mail.com", "password"=>"[FILTERED]"}
[1m[36mUser Load (1.4ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1[0m
Entered create method
[1m[35mUser Load (3.9ms)[0m SELECT "users".* FROM "users" WHERE "users"."email" = 'my@mail.com' LIMIT 1
Completed 200 OK in 99ms (Views: 0.3ms | ActiveRecord: 5.3ms)
然后,当我运行$curl-xpost”https://localhost:3000/api/v1/tokens.json?email=my@mail.com&password=somepassword“-d”电子邮件=my@mail.com&password=somepassword“-v-k-i
,我得到
Started POST "/api/v1/tokens.json?email=my@mail.com&password=[FILTERED]" for 127.0.0.1 at 2013-11-25 11:29:01 +0100
Processing by Api::V1::TokensController#create as JSON
Parameters: {"email"=>"my@mail.com", "password"=>"[FILTERED]"}
Completed 401 Unauthorized in 12ms
您可能会问,为什么我将参数同时作为HTTP Post数据和查询字符串提供。嗯,我对curl-lib样本的初步研究表明了前者,而邮递员的成功查询表明了后者。我试过所有这些组合,但都不起作用,所以我很迷茫
在Api::V1::tokenscoontroller
中,我在调用create方法时添加了日志记录,即
class Api::V1::TokensController < ApplicationController
skip_before_filter :verify_authenticity_token
respond_to :json
def create
Rails.logger.debug("Entered create method")
email = params[:email]
password = params[:password]
if request.format != :json
render :status=>406, :json=>{:message=>"The request must be json"}
return
end
if email.nil? or password.nil?
render :status=>400,
:json=>{:message=>"The request must contain the user email and password."}
return
end
@user=User.find_by_email(email.downcase)
if @user.nil?
logger.info("User #{email} failed signin, user cannot be found.")
render :status=>401, :json=>{:message=>"Invalid email or password."}
return
end
# http://rdoc.info/github/plataformatec/devise/master/Devise/Models/TokenAuthenticatable
@user.ensure_authentication_token!
if not @user.valid_password?(password)
logger.info("User #{email} failed signin, password \"#{password}\" is invalid")
render :status=>401, :json=>{:message=>"Invalid email or password."}
else
render :status=>200, :json=>{:token=>@user.authentication_token}
end
end
def destroy
@user=User.find_by_authentication_token(params[:id])
if @user.nil?
logger.info("Token not found.")
render :status=>404, :json=>{:message=>"Invalid token."}
else
@user.reset_authentication_token!
render :status=>200, :json=>{:token=>params[:id]}
end
end
end
class Api::V1::TokensController406,:json=>{:message=>“请求必须是json”}
返回
结束
如果email.nil?还是密码。零?
渲染:状态=>400,
:json=>{:message=>“请求必须包含用户电子邮件和密码。”}
返回
结束
@用户=用户。通过电子邮件查找(email.downcase)
如果@user.nil?
info(“用户#{email}登录失败,找不到用户。”)
render:status=>401,:json=>{:message=>“无效的电子邮件或密码。”}
返回
结束
# http://rdoc.info/github/plataformatec/devise/master/Devise/Models/TokenAuthenticatable
@user.sure\u身份验证\u令牌!
如果不是@user.valid\u密码?(密码)
logger.info(“用户{email}登录失败,密码\”{password}\“无效”)
render:status=>401,:json=>{:message=>“无效的电子邮件或密码。”}
其他的
render:status=>200,:json=>{:token=>@user.authentication\u token}
结束
结束
def销毁
@user=user.find\u by\u authentication\u令牌(params[:id])
如果@user.nil?
logger.info(“找不到令牌”)
render:status=>404,:json=>{:message=>“无效令牌”。}
其他的
@user.reset\u身份验证\u令牌!
render:status=>200,:json=>{:token=>params[:id]}
结束
结束
结束
从日志中可以看出,create方法在第一个位置被调用,而不是在第二个位置被调用。这就好像Api::V1::tokenscocontroller
的skip_before_filter:verify_authenticity_token
被完全忽略。但这怎么可能呢
非常感谢您的任何建议 我就是这么做的。对于常规html视图,为了方便用户,我希望继续使用cookie。对于(移动)RESTAPI,我想禁用Cookie,因为整个过程都将使用
auth_token
我不是Rails/Desive的超级英雄,所以我对此有点动摇,但我认为这应该没问题。。。无论如何:在完全点击令牌控制器之前,我禁用了身份验证。为了从tokens控制器中获得合理的信息,您必须提供匹配的电子邮件/密码凭据对,因此我(目前)看不到这种方法存在任何明显的安全漏洞
因此,我的新TokensController如下所示:
class Api::V1::TokensController < ApplicationController
skip_before_filter :verify_authenticity_token
skip_before_filter :authenticate_player!
respond_to :json
def create
# ....
class Api::V1::TokensController
希望这能帮助其他人。如果您对可能的安全问题有任何反馈,我们将不胜感激
更新:
我忘了提到,到目前为止,整个应用程序都是通过HTTPS进行通信的。我的直觉是,您没有为json正确发送curl。看看chrome开发工具中的网络选项卡,您可以将请求复制为cURL格式。尝试将其与您正在发送的内容进行比较,以查看缺少的内容。尝试使用类似于
curl-d''的curl的basic posthttps://localhost:3000/api/v1/tokens.json?email=my@mail.com&password=password
我也看到了您的请求,并且https
请求localhost查看是否需要这样做如果需要,然后,也许您提供了curl证书或使用--无检查证书
,无论哪种方式,它都会工作,因为我一直在使用它,这要感谢这三个方面的宝贵建议。最后,@Slicedpan引导我找到了解决方案——似乎在使用Postman时设置了cookie。我会在适当的时候写一个答案。:)邮递员将使用为域设置的任何现有Cookie(过去给我带来了一些麻烦!)