在 Rails API + React 客户端中实现用户模拟

Ole*_*nko 19 ruby impersonation client-server ruby-on-rails devise

所以,我发现了像fakeruser_impersonate2switch_user这样的宝石。他们似乎都实现了相似的目标——转向current_user像 Devise 这样的系统,转向“整体”Rails 应用程序。

我有一个 React 客户端与 Rails 应用程序通信。管理页面直接在Rails中实现(它是一个视图),并且客户端是分离的。目前,客户端向提供access_tokenvia的 Devise 路由发出 POST 请求devise-jwt,并将令牌保存在浏览器的localstorage.

是否有推荐的方法允许管理员以用户身份登录并从管理(Rails)页面重定向到客户端(React)页面?最好对前端代码进行最少的更改,但我可以解决这个问题。

我考虑过通过共享根域共享 cookie,但这对我来说存在安全问题。

我不确定如何使客户端应用程序“侦听”Rails 应用程序中所做的令牌更改,或者从客户端的角度更改当前用户的任何类似方式。

And*_*dyV 0

我不会建议这样做,但我会告诉您我所采取的基本方法。

在构建 JWT 时,我们包含一些关键的用户信息,以便从令牌中识别用户。查看 devise-jwt 文档,最简单的解决方案如下:

def jwt_payload
  { uid: id }
end
Run Code Online (Sandbox Code Playgroud)

接下来,您必须确保可以共享用于创建 JWT 的秘密。我是 12-factor 的粉丝,因此我们的解决方案使用环境变量来实现类似的目的。

最后,我们从标头中读取 JWT、解密并查找用户。这假设您共享用户数据库或复制用户。我们将其构建到包含在 ApplicationController 中的模块中。调整我们的,上面的有效负载看起来像这样:

module JwtTokenable
  private

  def token_user
    user_id = token_payload.dig(:uid)
    # CUSTOMIZE BELOW
    User.find(user_id) if user_id
  end

  def token_payload
    @payload ||= JWT.decode(access_token, ENV.fetch('JWT_SECRET', ''), true, { algorithm: 'HS512' })
                    .first
                    .deep_symbolize_keys
  rescue JWT::DecodeError
    return {}
  end

  def access_token
    @access_token ||= authorization_header.split.last
  end

  def authorization_header
    request.headers['Authorization'] || ''
  end
end
Run Code Online (Sandbox Code Playgroud)

模拟的最后一步是“CUSTOMIZE BELOW”注释所在的位置。此代码只是通过 ID 查找用户。那时,您也许可以利用您提到的其中一个宝石来确定是否需要返回用户或任何被冒充的人。