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

Rails 5 API基于Devise的Cookie认证在Cucumber中无法正常工作

嘿,我看你在给自研的Rails 5 API写Cucumber认证特性时,卡在了Devise Cookie认证的测试环节。先把你提供的authentication.feature文件按规范格式化出来,方便咱们后续排查:

Feature: Authentication
  As an existing user
  I would like to sign in the app

  Background:
    Given the following user exists:
      | id | email            | password   |
      | 1  | user@example.com | 12345678   |

  Scenario: Sign in
    When I perform a POST request with email "user@example.com" and password "12345678" to "/users/sign_in"
    Then I should receive a 200 OK response
    And the response should set a "session_id" cookie

接下来咱们一步步解决问题,我分享几个踩过的坑和对应的解决方案:

1. 搞定步骤定义的正确实现

在features/step_definitions/authentication_steps.rb里添加以下代码,注意Devise的参数格式和密码加密要求:

背景步骤:创建测试用户

Given("the following user exists:") do |table|
  table.hashes.each do |user_attrs|
    # Devise要求密码加密,绝对不能直接存明文!
    User.create!(
      id: user_attrs['id'].to_i,
      email: user_attrs['email'],
      password: user_attrs['password'],
      password_confirmation: user_attrs['password']
    )
  end
end

登录请求步骤

When("I perform a POST request with email {string} and password {string} to {string}") do |email, password, path|
  # 发送POST请求时,要符合Devise的参数嵌套规则,还要设置Accept头支持JSON
  post path, params: {
    user: {
      email: email,
      password: password
    }
  }, headers: {
    'Accept' => 'application/json'
  }
end

响应验证步骤

Then("I should receive a {int} OK response") do |status_code|
  expect(response.status).to eq(status_code)
end

Then("the response should set a {string} cookie") do |cookie_name|
  expect(cookies[cookie_name]).to be_present
end

2. 关键配置不能忘(Rails API模式的坑)

Rails 5 API模式默认不会加载Cookie和Session中间件,但Devise Cookie认证依赖它们!所以必须在config/application.rb里添加:

config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore

同时调整config/initializers/devise.rb的配置,让Devise适配API场景:

# 关闭HTTP基本认证,改用Cookie认证
config.http_authenticatable = false
# 让Devise识别JSON格式的请求
config.navigational_formats = ['*/*', :html]
# 可选:根据你的路由设置登出方式
config.sign_out_via = :delete

3. 检查用户模型的Devise模块

确保你的User模型已经包含了:database_authenticatable模块,这是密码认证的核心:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end

常见排查点

  • 如果你还是认证失败,先检查测试数据库里的用户密码是不是加密过的(直接查encrypted_password字段,不能是明文)
  • 确认请求的参数是嵌套在user键下的,Devise不接受顶级的email/password参数
  • 用puts response.body在步骤里打印响应内容,看看Devise返回的错误信息(比如密码错误、用户不存在)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:41:29