如何在Doorkeeper中配置两种不同过期时长的访问令牌?
实现Doorkeeper双时长访问令牌方案
1. 配置Doorkeeper初始化器
修改config/initializers/doorkeeper.rb,设置默认过期时间并定义自定义过期逻辑:
Doorkeeper.configure do # 默认短有效期:2小时 access_token_expires_in 2.hours # 自定义过期逻辑,根据传入的上下文参数判断 custom_access_token_expires_in do |context| # 当上下文携带long_lived标记时,返回1年有效期,否则用默认值 context[:long_lived] ? 1.year : access_token_expires_in end end
2. 调整令牌创建逻辑
修改DoorkeeperRegisterable concern,新增参数控制令牌有效期,调用自定义过期逻辑:
module DoorkeeperRegisterable extend ActiveSupport::Concern # 新增long_lived参数,默认使用短有效期 def render_user(user, client_app, token_type = 'Bearer', long_lived = false) access_token = Doorkeeper::AccessToken.create( resource_owner_id: user.id, application_id: client_app.id, # 传入上下文参数,触发对应过期逻辑 expires_in: Doorkeeper.configuration.custom_access_token_expires_in.call(long_lived: long_lived), scopes: '' ) { id: user.id, access_token: access_token.token, token_type: token_type, expires_in: access_token.expires_in, created_at: access_token.created_at.to_time.to_i } end end
3. 在授权端点区分场景
在处理/api/v1/oauth/token的控制器中,判断请求类型,针对密码授权流程触发长有效期令牌:
class Api::V1::Oauth::TokensController < Doorkeeper::TokensController def create if params[:grant_type] == 'password' && valid_user_credentials? user = User.find_by(email: params[:email]) client_app = Doorkeeper::Application.find_by(client_id: params[:client_id]) render json: render_user(user, client_app, 'Bearer', true) else # 非密码授权流程,沿用Doorkeeper默认逻辑(短有效期) super end end private def valid_user_credentials? user = User.find_by(email: params[:email]) user&.authenticate(params[:password]) end end
核心逻辑说明
custom_access_token_expires_in的block参数context是自定义传入的哈希,用来传递场景标识,这里用:long_lived区分长短有效期。- 密码授权场景下明确传入
long_lived: true,触发1年有效期;其他授权方式(如客户端凭证、刷新令牌)自动使用默认2小时有效期。 - 无需直接硬编码过期时间,通过Doorkeeper配置统一管理,便于后续调整。
内容的提问来源于stack exchange,提问作者Owen Roth
相关产品推荐
相关产品推荐

