ruby-on-rails - devise_token_auth 总是返回 401 Unauthorized
问题描述
我正在开发一个带有 Rails API 的 Angular 应用程序。我正在使用Devise Token Auth和angular-token 的 6.x 分支。我可以毫无问题地 CRUD 用户,并且可以登录,但是当我尝试访问受限制的资源(通过before_action :authenticate_user!
帮助程序限制的资源)时,无论我是否登录,我都会收到错误消息。
相关控制器:
class QuestionsController < ApplicationController
before_action :authenticate_user!
# GET /questions.json
def index
@questions = Question.all
# This code is never reached due to the :authenticate_user! helper,
# but when I comment it out, I get the following:
puts user_signed_in? # => false
puts current_user # => nil
render json: @questions
end
一些东西:
- 我肯定是根据
angular-token
-时的TokenService.UserSignedIn()
回报登录true
的401 Unauthorized response
。 - 我已经启用了 CORS。
- 我在 rack-cors 配置中公开了以下标头
['access-token', 'expiry', 'token-type', 'uid', 'client']
:
任何帮助将不胜感激。
来自登录的示例响应:
{
"data": {
"id": 1,
"email": "me@example.com",
"provider": "email",
"uid": "me@example.com",
"allow_password_change": false,
"name": null,
"nickname": null,
"image": null
}
}
角码:
this.authService.loginUser({
login: '',
password: ''
})
.subscribe(resp => {
if (resp.status === 200) {
this.router.navigate(['/']);
}
},
err => {
// cut for brevity
});
编辑:
我发现问题在于angular-token
未设置身份验证标头,因为我认为这是以下代码中的错误:
// Add the headers if the request is going to the configured server
if (this.tokenService.currentAuthData && req.url.match(this.tokenService.apiPath)) {
(<any>Object).assign(baseHeaders, {
'access-token': this.tokenService.currentAuthData.accessToken,
'client': this.tokenService.currentAuthData.client,
'expiry': this.tokenService.currentAuthData.expiry,
'token-type': this.tokenService.currentAuthData.tokenType,
'uid': this.tokenService.currentAuthData.uid
});
}
由于我没有apiPath
定义,因此req.url.match(this.tokenService.apiPath))
被评估为false
,因此永远不会添加标题。
解决方案
我不知道 angular-token,但我的基于 React/Redux 的应用程序也遇到了同样的问题 - 事实证明,这确实只是标题丢失或未正确设置的问题。
出于某种原因,基于控制器似乎DeviseTokenAuth::
只能通过设置client
和工作access-token
,但对于所有其他受保护的资源DeviseTokenAuth::Concerns::SetUserByToken
,您必须完全按照预期设置all
标头,并由 devise_token_auth 记录。
- 检查标题值和格式。
- 检查标头是否完全等于最后一个请求(在您的情况下为身份验证请求)返回的标头。
- 另外,检查您的映射
在config/initializers/devise_token_auth.rb
:
config.headers_names = {:'access-token' => 'access-token',
:'client' => 'client',
:'expiry' => 'expiry',
:'uid' => 'id',
:'token-type' => 'token-type' }
(它定义了预期的 http 标头的名称(不是模型/活动记录属性))。
推荐阅读
- powershell - PowerShell 脚本无法在远程服务器上执行批处理文件
- git - Gitlab + Ansible 部署/管理多个集群
- excel - 在不同文件中拆分 Excel 工作表并将特定列中的数据复制到新文件中
- android - FLutter - 尝试运行应用程序时出错
- java - 项目正在寻找数据源,但我正在使用 MongoDB
- angular - 量角器在页面中找不到选择器
- primefaces - 为什么用 JSF 2.3 验证另一种形式的组件?
- javascript - JavaScript 或 jQuery 将表格的最后一行加粗并删除超链接。ID 为“My_Table_1”的表
- jquery - 如何简化此代码(通过使用循环?)
- mysql - 多个表的 JOIN 语句不起作用