我在AngularJS中有一个前端,在RoR中有一个后端,其中有+ RocketPants.现在我已经有了正常工作的CORS,我可以成功地从我的API中获得json响应(如果我关闭门卫保护的话)。但现在我正在尝试实现用户密码凭据流:
关于看门人:
resource_owner_from_credentials do |routes|
request.params[:user] = {:email => request.params[:username], :password => request.params[:password]}
request.env["devise.allow_params_authentication"] = true
request.env["warden"].authenticate!(:scope => :user)
end关于angularjs (src:nils-blum):
var payload = "username="+username+"&password="+password+"&" +
"client_id="+client_id+"&client_secret="+client_secret+
"&grant_type=password"
$http({method: 'POST',
url: scope.booksh_server + '/oauth/token',
data: payload,
headers: {'Content-Type':'application/x-www-form-urlencoded'}
}
).success(function (data) {
tokenHandler.set(data.access_token);
scope.$broadcast('event:authenticated');
});注意:Nils的方法使用带params的有效负载作为对象,而不是字符串。在我的例子中,它给了我带有效负载的POST,而不是表单params,因此无法工作。
当我输入错误的用户/密码时,rails日志说:
Started POST "/oauth/token" for 127.0.0.1 at 2013-11-22 15:21:08 +0400
Doorkeeper::Application Load (0.5ms) SELECT "oauth_applications".* FROM "oauth_applications" WHERE "oauth_applications"."uid" = '981d6d654f5e709b2ca3437401c993a6d09cc91cc3fb16b8e2b3191e6421029c' AND "oauth_applications"."secret" = 'f92c4ec969525352bd03ec1eb810a9952cd0814d37ce5b2b02e8a928b2561e10' ORDER BY "oauth_applications"."id" ASC LIMIT 1
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."email" = 'undefined' ORDER BY "users"."id" ASC LIMIT 1Chrome工具显示此请求被取消。Firebug显示302找到状态的空响应。当我从chrome REST App执行相同的帖子时,UPD: server也会这样做,然后找到302,然后将其重定向到sign_in页面。
此外,如果输入正确的用户/密码,firefox将显示为200 OK的空响应,REST使用访问令牌接收适当的json,而chrome显示取消的响应并抛出CORS错误:
XMLHttpRequest cannot load http://0.0.0.0:3000/oauth/token. Origin http://0.0.0.0:9000 is not allowed by Access-Control-Allow-Origin. 服务器日志:
Started POST "/oauth/token" for 127.0.0.1 at 2013-11-22 15:33:22 +0400
Doorkeeper::Application Load (0.5ms) SELECT "oauth_applications".* FROM "oauth_applications" WHERE "oauth_applications"."uid" = '981d6d654f5e709b2ca3437401c993a6d09cc91cc3fb16b8e2b3191e6421029c' AND "oauth_applications"."secret" = 'f92c4ec969525352bd03ec1eb810a9952cd0814d37ce5b2b02e8a928b2561e10' ORDER BY "oauth_applications"."id" ASC LIMIT 1
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."email" = '123@gmail.com' ORDER BY "users"."id" ASC LIMIT 1
(0.2ms) BEGIN
SQL (0.4ms) UPDATE "users" SET "last_sign_in_at" = $1, "current_sign_in_at" = $2, "sign_in_count" = $3, "remember_token" = $4, "updated_at" = $5 WHERE "users"."id" = 1 [["last_sign_in_at", Fri, 22 Nov 2013 11:32:49 UTC +00:00], ["current_sign_in_at", Fri, 22 Nov 2013 11:33:23 UTC +00:00], ["sign_in_count", 24], ["remember_token", "N5sRI6vE7B6vRNUlih3G2Q"], ["updated_at", Fri, 22 Nov 2013 11:33:23 UTC +00:00]]
(17.5ms) COMMIT
(1.6ms) BEGIN
Doorkeeper::AccessToken Exists (0.3ms) SELECT 1 AS one FROM "oauth_access_tokens" WHERE "oauth_access_tokens"."token" = '72dd81fd85b638fb14f9d081193b1eda0e58f85d6820718ab635fe195c36a689' LIMIT 1
SQL (0.3ms) INSERT INTO "oauth_access_tokens" ("application_id", "created_at", "expires_in", "resource_owner_id", "scopes", "token") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["application_id", 1], ["created_at", Fri, 22 Nov 2013 11:33:23 UTC +00:00], ["expires_in", 7200], ["resource_owner_id", 1], ["scopes", ""], ["token", "72dd81fd85b638fb14f9d081193b1eda0e58f85d6820718ab635fe195c36a689"]]
(28.1ms) COMMIT我怎么才能把这事做好?如果电子邮件/密码是正确的,我需要POST /oauth/令牌来处理身份验证并使用access_token进行响应。任何帮助都是值得感激的,我厌倦了被困在这上面
发布于 2013-11-22 23:29:54
耶!我终于成功了。仍然不知道为什么在网络上的教程中,这要容易得多。
因此,问题来自何处:在我的ApplicationController (根ApplicationController,而不是处理API的根)中,我为CORS提供了以下内容:
before_filter :set_headers
def set_headers
headers['Access-Control-Allow-Origin'] = 'http://0.0.0.0:9000'
headers['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD'
headers['Access-Control-Allow-Headers'] = '*,X-Requested-With,Content-Type,If-Modified-Since,If-None-Match'
headers['Access-Control-Max-Age'] = '86400'
end深入研究这个问题,我发现这个函数不是在调用/oauth/token时调用的,而是在使用ApplicationController处理的API之外的任何其他路由时调用的。
门卫有自己的控制器独立于您的应用程序控制器。Docs很好地描述了他们行为的变化(link),下面是帮助我的地方:
routes.rb:
use_doorkeeper do
controllers tokens: 'custom_tokens'
endcustom_tokens_controller.rb:
class CustomTokensController < Doorkeeper::TokensController
include AbstractController::Callbacks
before_filter :set_headers
def set_headers
puts 'headers set'
headers['Access-Control-Allow-Origin'] = 'http://0.0.0.0:9000'
headers['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD'
headers['Access-Control-Allow-Headers'] = '*,X-Requested-With,Content-Type,If-Modified-Since,If-None-Match'
headers['Access-Control-Max-Age'] = '86400'
end
end重要的是将Callbacks包含到控制器中,因为Doorkeeper控制器是从Metal继承的,因此没有包含rails就无法找到before_filter。
它现在看起来很好:它对我的用户/密码对进行身份验证,并返回access_token (我希望它能工作:D )。如果出了什么问题,现在就该重定向了。这就是我所知道的解决方案(自定义典狱长故障),所以现在一切都好了。哈!太长了..。如果有人知道为什么基于互联网的食谱没有帮助,请张贴你的想法=)
https://stackoverflow.com/questions/20144210
复制相似问题