当我尝试接收来自外部Api的JSON响应中应包含的访问令牌时,我遇到了rails和faraday的问题。
我想要做的是基于外部API的用户身份验证。 我假设用户已经拥有有效的凭据(在这种情况下,电子邮件是用户名和密码)。
现在当他连接到我的Api时,我将JSON请求发送到外部Api以验证该用户是否有效并等待访问令牌。
在响应中发送访问令牌后,用户身份验证成功,我可以访问其他端点
这是我的控制器
module Api
class AuthenticationController < ApplicationController
def create
client = XXX::AuthClient.new
response = client.authenticate(
email: params[:email],
password: params[:password]
)
api_client = XXX::Client.new(response[:access_token])
if response[:access_token]
api_user = api_client.get_user()
if api_user["id"]
db_user = User.create(xxx_id: api_user["id"], xxx_access_token: response[:access_token])
end
end
render json: { access_token: db_user.access_token }
end
end
end
这是我的AuthClient服务
class AuthClient
def initialize
@http_client = Faraday.new('https://auth.xxx.com/')
end
def authenticate(email:, password:)
headers = {
'Content-Type': 'application/json'
}.to_json
body = {
grant_type: "password",
username: email,
password: password,
client_id: "particularclientid",
client_secret: "particularclientsecret"
}.to_json
api_response = http_client.post("/oauth2/token", body)
response = JSON.parse(api_response.body)
if response["access_token"]
{ access_token: access_token }
else
{ error: "autentication error" }
end
end
private
attr_reader :http_client
end
end
我所知道的是以下格式的卷曲是正确的,我可以看到用户的访问令牌,刷新令牌等。
curl -X POST -H "Content-Type: application/json" -d '{
"grant_type": "password",
"username": "test+user@example.com",
"password": "examplepassword",
"client_id": "particularclientid",
"client_secret": "particularclientsecret"
}' "https://auth.xxx.com/oauth2/token"
但是当我运行我的卷曲时
curl -X POST -d 'email=test+user@example.com&password=examplepassword' "http://localhost:3000/api/auth"
我看到我的请求不正确。但我不知道问题在哪里,因为标题和正文被格式化为JSON(我已输入puts headers
,puts body
和puts response
来验证这一点。
Started POST "/api/auth" for 127.0.0.1 at 2017-03-31 16:42:26 +0200
Processing by Api::AuthenticationController#create as */*
Parameters: {"email"=>"test user@example.com", "password"=>"[FILTERED]"}
{"Content-Type":"application/json"}
{"grant_type":"password","username":"test user@example.com","password":"examplepassword","client_id":"particularclientid","client_secret":"particularclientsecret"}
{"error"=>"invalid_request", "error_description"=>"The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed."}
Completed 500 Internal Server Error in 610ms (ActiveRecord: 0.0ms)
NoMethodError (undefined method `access_token' for nil:NilClass):
app/controllers/api/authentication_controller.rb:21:in `create'
我的请求不正确或问题是否存在于其他地方? 我不是经验丰富的开发者。只是想学习足以开始作为少年RoR。我试图在堆栈和不同的网站上找到解决方案,但我被困了。即使是法拉第文档对我也没有多大帮助
答案 0 :(得分:0)
确定。 当我再次开始阅读我的帖子时,我又发现了一个问题。
我的控制器无法识别用户名字段中的加号,而是由空格替换。
我发送curl -X POST -d 'email=test+user@example.com&...
在控制器中,我看到"username":"test user@example.com"
但这并不能解决我的问题。
答案 1 :(得分:0)
转义URI时,+
用作空格的替代。因此,当您的控制器取消转义URI时,+
将更改回空间。如果您想发送空格,请改用%2B
。
对于您的第一个问题,当您尝试执行db_user
时,错误消息表明db_user.access_token
为零。因此,response[:access_token]
为零,api_user["id"]
为零,或User.create
失败。
您需要进行一些调试才能找出问题所在。
答案 2 :(得分:0)
我调试了控制器,当我在控制台中打印响应时,我看到了
response = client.authenticate(
email: params[:email],
password: params[:password]
)
puts response
我收到了{:error=>"autentication error"}
。
然后,这意味着当我向Client的Api
if response["access_token"]
{ access_token: access_token }
else
{ error: "autentication error" }
end
所以在这种情况下唯一可能出错的是我的请求没有正确格式化(应该是JSON)或者在标题或正文中缺少某些内容。
def authenticate(email:, password:)
headers = {
'Content-Type': 'application/json'
}.to_json
body = {
grant_type: GRANT_TYPE,
username: email,
password: password,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
}.to_json
api_response = http_client.post("/oauth2/token", body)
response = JSON.parse(api_response.body)
以某种方式可以验证这里发送的是什么吗? api_response = http_client.post("/oauth2/token", body)
我已经尝试在此代码下面插入puts,我在控制台中看不到任何内容。