如何在Rails控制台中使用Devise登录用户?

55

在加载Rails控制台后,我应该如何登录用户?

Devise提供了一个测试助手,可以在测试中使用,我已经尝试在控制台中使用:

>> include Devise::TestHelpers
>> helper.sign_in(User.first)

但是我得到:

NoMethodError: undefined method `env' for nil:NilClass

无论如何,我想使用真正的Devise帮助程序而不是这个测试帮助程序。是否有任何方法可以实现这一点?

5个回答

88

以下是我能够做到的一种方法:

>> ApplicationController.allow_forgery_protection = false
>> app.post('/sign_in', {"user"=>{"login"=>"login", "password"=>"password"}})

然后你可以这样做:

 >> app.get '/some_other_path_that_only_works_if_logged_in'
 >> pp app.response.body

2
使用现代的Devise,您将需要使用email而不是loginapp.post('/sign_in', {"user"=>{"email"=>"login", "password"=>"password"}}) - Xavier
2
在这个上下文中,“app”是如何初始化的? - Nona
应用程序在启动控制台时初始化。您无需执行任何额外操作。 - Brian Deterling
我不得不使用app.post('/users/sign_in', {params: {"email"=>"[FILTERED]", "password"=>"[FILTERED]"}}),但除此之外它非常好用,谢谢!有关forgery_protection的那一部分可能会让我卡一整天! - Mirv - Matt

16

这是另一个例子,它使用 CSRF 令牌,验证用户,并进行 POST/GET 请求。

# get csrf token
app.get  '/users/sign_in'
csrf_token = app.session[:_csrf_token]

# log in
app.post('/users/sign_in', {"authenticity_token"=>csrf_token, "user"=>{"email"=>"foo", "password"=>"bar"}})

# get new csrf token, as auth user
app.get ''
csrf_token = app.session[:_csrf_token]

# make a POST request
app.post '/some_request.json', {"some_value"=>"wee", "authenticity_token"=>csrf_token}

# make a GET request
app.get '/some_other_request.json'

一个旧的答案,但仍然适用。这是对我来说正确的答案! - Peter Andersson
传递参数到app.post的语法已更改为app.post '/users/sign_in', params: {"authenticity_token"=>csrf_token, .... - Roger Marlow
对于Rails 6,您可能需要将config.hosts.clear添加到您的development.rb文件中 - 如此处所述 - anotherdave

4
需要注意的是,自从 Rails 5以后,参数解析已经被改为只接受一个参数和params(而不是params作为第二个参数)。

ActionDispatch :: ParamsParser已弃用并已从中间件堆栈中删除。要配置参数解析器,请使用ActionDispatch :: Request.parameter_parsers =

因此,在现代Rails中,这些早期的示例将不再起作用,除非您修补中间件。 要使它们工作,只需在POST参数中包含参数即可: app.post('/users/sign_in',{"user"=>{"email"=>"me@mail.com","password"=>"mycoolpassword"}}) <-- 不再有效 app.post('/users/sign_in',params:{"user"=>{"email"=>"me@mail.com","password"=>"mycoolpassword"}}) <-- 有效

3

您可以在您的控制器内添加一个操作,并使用 这里 解释的技术。

class MyController < ApplicationController
  # POST /my_controller/become {'email': 'test@example.com'}
  def become
    raise 'not in development environment' unless Rails.env == 'development'
    sign_in User.find_by_email(params[:email])
  end
end

这并没有真正回答问题,因为问题是关于从控制台登录,而不是从Web应用程序中以另一个用户身份登录。 - Martin Tournoij
1
但它仍然很有用,你也可以从控制台调用这个方法。我通过谷歌搜索到这里,是的,上面的答案很好并且有效,但这个对我也很有帮助。所以不要像这样一直给任何人负面评价。 - user1735921
有没有办法在控制台上使用 sign_in?因为我需要生成一个令牌访问,但这将发生在登录之后。 - vinicius gati

0

有更好的方法可以做到这一点。将此代码添加到config/application.rb中

# config/pplication.rb

  class Application < Rails::Application
    # ...
    console do
      class ActionDispatch::Integration::Session
        def host; 'localhost'; end
      end

      class ::BackdoorController < Devise::SessionsController
        def comeonin
          sign_in $current_user
          render json: {}
        end
      end
      Rails.application.routes.disable_clear_and_finalize = true
      Rails.application.routes.draw do
        devise_scope(:user) { get '/backdoor', to: "backdoor#comeonin" }
      end
    end
    # ...
  end

现在您可以代表任何用户登录:

$current_user = User.last
app.get '/backdoor' # sign in
app.get '/profile' # any other request

在HTTPS的情况下,可能需要使用完整的主机名:

app.get 'https://localhost/backdoor'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接