You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展如何实现与Ruby on Rails后端对接的会话管理

Rails + Devise 对接 Chrome 扩展会话实现方案

后端适配配置

  1. 跨域配置
    在config/initializers/cors.rb中添加扩展的跨域许可,注意替换为你实际的扩展ID和后端域名:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'chrome-extension://<你的扩展ID>'
    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head],
      credentials: true
  end
end
  1. 自定义Devise会话控制器
    执行命令生成自定义Devise控制器:
    rails generate devise:controllers users
    修改app/controllers/users/sessions_controller.rb的create方法,登录成功后返回Session ID:
class Users::SessionsController < Devise::SessionsController
  skip_before_action :verify_authenticity_token
  respond_to :json

  def create
    self.resource = warden.authenticate!(auth_options)
    sign_in(resource_name, resource)
    render json: { user: resource.as_json(only: [:id, :email]), session_key: session.id }
  end

  def destroy
    signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
    render json: { code: 0, msg: '登出成功' }
  end
end

修改config/routes.rb指定Devise使用自定义控制器:

devise_for :users, controllers: {
  sessions: 'users/sessions'
}
  1. Session配置
    修改config/initializers/session_store.rb支持从请求头读取Session ID:
Rails.application.config.session_store :cookie_store,
  key: '_your_app_session', # 替换为你的应用session key名
  cookie_only: false,
  same_site: :none,
  secure: Rails.env.production?

在app/controllers/application_controller.rb添加前置钩子,优先从请求头加载会话:

class ApplicationController < ActionController::Base
  before_action :load_session_from_header

  private
  def load_session_from_header
    if request.headers['X-SESSION-ID'].present?
      session.id = request.headers['X-SESSION-ID']
    end
  end
end

后续业务接口直接使用Devise自带的authenticate_user!方法鉴权即可,无需额外修改。

Chrome扩展侧实现

  1. Manifest权限配置
    在manifest.json中添加后端域名访问许可:
{
  "host_permissions": ["https://<你的后端域名>/*"],
  "permissions": ["storage"]
}
  1. 登录逻辑
    用户提交登录表单时发起鉴权请求,成功后存储Session ID到扩展全局存储:
// 登录请求示例
const handleLogin = async (email, password) => {
  const res = await fetch('https://<你的后端域名>/users/sign_in', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      user: { email, password }
    }),
    credentials: 'include'
  })
  const data = await res.json()
  await chrome.storage.local.set({ sessionKey: data.session_key, userInfo: data.user })
}

注意使用chrome.storage.local而非普通localStorage,扩展不同上下文(popup、content script、background)的localStorage相互隔离,chrome.storage为全局共享存储。

  1. 鉴权请求封装
    后续所有需要登录态的请求,都在请求头携带存储的Session ID:
// 封装通用请求方法
const authFetch = async (url, options = {}) => {
  const { sessionKey } = await chrome.storage.local.get('sessionKey')
  const defaultHeaders = {
    'Content-Type': 'application/json',
    'X-SESSION-ID': sessionKey
  }
  options.headers = { ...defaultHeaders, ...options.headers }
  options.credentials = 'include'
  return fetch(`https://<你的后端域名>${url}`, options)
}

// 使用示例
const getMyData = async () => {
  const res = await authFetch('/api/my-data', { method: 'GET' })
  return res.json()
}
  1. 登出逻辑
    调用登出接口后清除本地存储的Session ID即可:
const handleLogout = async () => {
  await authFetch('/users/sign_out', { method: 'DELETE' })
  await chrome.storage.local.remove(['sessionKey', 'userInfo'])
}

注意事项

  • 生产环境后端必须使用HTTPS,否则Chrome会拦截SameSite=None的Cookie,会话配置不生效
  • 若更倾向Token鉴权模式,可给Devise新增Token校验模块,登录后返回长期/短期有效Token,后续请求头携带Authorization: Bearer <Token>鉴权,无需处理Session跨域适配,更适合纯API场景

内容的提问来源于stack exchange,提问作者pixelearth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 10:36:01