我已经实施了Matteo Melanis伟大的博客文章A Simple Token Authentication Service for Mobile Devices。它与Chrome扩展程序Postman完美配合。但是,当我尝试使用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
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 -X POST "https://localhost:3000/api/v1/tokens.json?email=my@mail.com&password=somepassword" -d "email=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样本http-post.c的初步研究表明前者,而Postmans成功的查询表明后者。我已经尝试过这些的所有组合,但没有任何作用,所以我很丢失。
在Api::V1::TokensController
中,我在调用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
从日志中可以看出,create方法首先被调用,而不是在第二个中被调用。好像Api::V1::TokensController
的{{1}}完全被忽略了。但那怎么可能呢?
非常感谢任何建议!
答案 0 :(得分:0)
所以这就是我所做的。对于常规的html视图,我想继续使用cookie以方便用户。对于(移动)REST API,我想禁用cookie,因为auth_token
将在整个过程中使用。
我不是Rails / Devise的超级英雄,所以我对此有些不稳定,但我认为应该没问题......无论如何:我在完全击中令牌控制器之前禁用了身份验证。为了从令牌控制器中获得任何合理的信息,您必须提供匹配的电子邮件/密码凭证对,因此我不能(目前)通过这种方法看到任何明显的安全漏洞。
因此,我的新TokensController看起来像这样:
class Api::V1::TokensController < ApplicationController
skip_before_filter :verify_authenticity_token
skip_before_filter :authenticate_player!
respond_to :json
def create
# ....
希望这有助于其他人坚持到那里。任何有关可能的安全问题的反馈都非常感谢!
更新
我忘了提到,截至目前,整个应用程序都通过HTTPS进行通信。