使用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以获得更干净、更可靠的代码。

详情请参阅commitPR #56474