Doorkeeper撤销token时如何触发依赖request与user对象的自定义代码
Doorkeeper 执行Token撤销自定义逻辑的实现方案
Doorkeeper 确实没有提供开箱即用的Token撤销回调钩子,以下三种方案都可以实现需求,按推荐优先级排序:
方案1:重写默认撤销控制器(优先选,无兼容问题)
Doorkeeper 的Token撤销逻辑默认由Doorkeeper::TokensController的revoke动作处理,官方支持自定义控制器覆盖默认实现,这种方式可以直接拿到request对象,也能提前取出关联的用户信息,是最稳妥的实现方式。
- 首先修改路由配置,替换默认的tokens控制器:
# config/routes.rb Rails.application.routes.draw do use_doorkeeper do controllers tokens: "custom_tokens" end end
- 实现自定义控制器,在原有撤销逻辑前后插入你的业务代码:
# app/controllers/custom_tokens_controller.rb class CustomTokensController < Doorkeeper::TokensController def revoke # 必须在执行原撤销逻辑前取出token和关联用户,token被撤销/删除后将无法查询关联关系 access_token = Doorkeeper::AccessToken.by_token(request.POST["token"]) current_user = access_token&.resource_owner is_valid_token = access_token&.accessible? # 执行Doorkeeper原生的撤销逻辑 super # 撤销流程走完后执行自定义逻辑,request、current_user都可直接调用 if response.status == 200 && is_valid_token && current_user.present? # 此处写入你的自定义逻辑,例如记录审计日志、清理用户缓存、推送下线通知等 # 示例:UserAuditLog.create(user: current_user, event: "token_revoked", ip: request.remote_ip, ua: request.user_agent) end end end
注意:Doorkeeper的撤销接口对无效、不存在的token也会返回200状态码,如果你的逻辑只需要在真实有效token被撤销时触发,一定要提前通过accessible?判断token有效性。
方案2:给AccessToken模型加生命周期回调
如果你的逻辑对request信息依赖不强,可以直接给Doorkeeper的AccessToken模型加ActiveRecord回调,监听撤销状态的变更:
# 在config/initializers/doorkeeper.rb末尾追加 Doorkeeper::AccessToken.class_eval do # 仅当revoked_at字段从空变为有值时触发(即token刚被撤销) after_update :trigger_custom_revoke_logic, if: :saved_change_to_revoked_at? private def trigger_custom_revoke_logic current_user = resource_owner # 如果需要拿request对象,需要提前在全局请求上下文(例如Rails 7+的CurrentAttributes)中存储request对象,此处直接读取即可 # 写入你的自定义逻辑 end end
这个方案的缺点是request对象需要额外做上下文透传,适合轻量逻辑场景。
方案3:Rack中间件拦截撤销请求(不推荐)
可以自定义Rack中间件匹配/oauth/revoke路径的请求,在响应完成后解析参数、查询token和用户信息执行逻辑,但这种方式需要自己对齐Doorkeeper的撤销判定规则,后续Doorkeeper版本升级时容易出现逻辑不兼容,非特殊场景不建议使用。
避坑提醒:不要直接修改Doorkeeper源码或者直接重写原TokensController的方法,通过继承扩展的方式是官方认可的自定义路径,后续版本升级的维护成本最低。
内容的提问来源于stack exchange,提问作者Logan Keenan
相关产品推荐
相关产品推荐

