使用Request#bearer_token提取Bearer令牌
如果你正在用Rails构建API,你可能已经写过从Authorization头中提取bearer令牌的代码。Rails现在提供了一个内置方法来干净地完成这项工作。
变更内容
ActionDispatch::Request现在包含一个bearer_token方法,从Authorization头中提取令牌:
# Authorization: Bearer my-secret-token
request.bearer_token
# => "my-secret-token"
为什么这很重要
Bearer令牌是验证API请求的标准方式。在此变更之前,你会写类似这样的代码:
class ApiController < ApplicationController
def authenticate
token = request.authorization.to_s.split(" ").last
# 或
token = request.authorization&.gsub(/^Bearer /, "")
# 或
token = request.headers["Authorization"]&.match(/Bearer (.+)/)&.[](1)
end
end
每种方法都有边界情况。新方法处理了所有这些:
token = request.bearer_token
如何使用
基本API认证
class ApiController < ApplicationController
before_action :authenticate
private
def authenticate
token = request.bearer_token
unless token && valid_token?(token)
render json: { error: "未授权" }, status: :unauthorized
end
end
def valid_token?(token)
ApiToken.find_by(token: token)&.active?
end
end
与Devise或自定义认证一起使用
class ApiController < ApplicationController
before_action :authenticate_user_from_token!
private
def authenticate_user_from_token!
token = request.bearer_token
return head :unauthorized unless token
@current_user = User.find_by(api_token: token)
head :unauthorized unless @current_user
end
end
处理的边界情况
该方法在以下情况返回nil:
# 没有Authorization头
request.bearer_token # => nil
# 不同的认证方案
# Authorization: Basic dXNlcjpwYXNz
request.bearer_token # => nil
# 空头
# Authorization:
request.bearer_token # => nil
# Bearer没有令牌
# Authorization: Bearer
request.bearer_token # => nil
它也适用于X-HTTP_AUTHORIZATION头(某些代理使用):
# X-HTTP_AUTHORIZATION: Bearer my-token
request.bearer_token # => "my-token"
注意事项
- 该方法只提取令牌;验证仍然是你的责任
- 令牌区分大小写;该方法保留确切的令牌值
- “Bearer”前缀匹配区分大小写(根据RFC 6750)
总结
一个小而受欢迎的补充,消除了API认证代码中的样板代码。如果你正在手动解析Authorization头,请切换到request.bearer_token以获得更干净、更可靠的代码。