无法在Sinatra App中使用Warden:env ['warden']返回nil

时间:2012-11-06 00:33:59

标签: ruby sinatra rack warden

我正在编写Sinatra Rack App,我想使用Warden进行身份验证。我正在使用heroku的工具带,所以我使用工头来运行我的应用程序。我发现some code大概应该让这个工作起来。不幸的是,当我试图实际访问Warden env对象时,它是零。

我试图使用sinatra_warden gem,但它也有own bugs(可能与此相关)。

config.ru:

require './web.rb'
use Rack::Static, :urls => ["/css", "/img", "/js"], :root => "public"
run MyApp

web.rb:

require 'sinatra'
require 'warden'
require 'data_mapper'

require './config/datamapper.rb'
require './config/warden.rb' # I've tried this inside of MyApp, still didn't work

class MyApp < Sinatra::Base

  get '/test' do
    env['warden'].authenticate! # env['warden'] is nil :(
  end

end

配置/ warden.rb:

use Rack::Session::Cookie, :secret => ENV['SESSION_SECRET']

use Warden::Manager do |manager|
  manager.default_strategies :password
  manager.failure_app = MyApp.new
end

Warden::Manager.serialize_into_session { |user| user.id }
Warden::Manager.serialize_from_session { |id| User.get(id) }

Warden::Manager.before_failure do |env,opts|
  # Sinatra is very sensitive to the request method
  # since authentication could fail on any type of method, we need
  # to set it for the failure app so it is routed to the correct block
  env['REQUEST_METHOD'] = "POST"
end

Warden::Strategies.add(:password) do
  def valid?
    params["email"] || params["password"]
  end

  def authenticate!
    u = User.authenticate(params["email"], params["password"])
    u.nil? ? fail!("Could not log in") : success!(u)
  end
end

版本:

  • Sinatra:1.1.0
  • 守望者:1.2.1
  • Rack:1.4.1
  • Ruby:1.9.3p194
  • 工头:0.60.0

有关如何使用Warden设置的任何想法我已经描述过?

(P.S。出于好奇,env变量究竟是什么?)

2 个答案:

答案 0 :(得分:3)

Rack内部使用类Rack::Builder来解析你的config.ru文件并包装指令以构建中间件组件。

我相信useconfig/warden.rb的构建者调用被忽略了。它可能会从该文件中删除指令并将它们添加到config.ru中的中间件堆栈中:

require './web.rb'

use Rack::Session::Cookie, :secret => ENV['SESSION_SECRET']

use Warden::Manager do |manager|
  manager.default_strategies :password
  manager.failure_app = MyApp.new
end

use Rack::Static, :urls => ["/css", "/img", "/js"], :root => "public"

run MyApp

答案 1 :(得分:0)

在config.ru

中添加指向config / warden的链接
require File.dirname(__FILE__) + '/config/warden'

阅读看守自述文件。或者在lib / warden.rb

中查看

我把

Warden.test_mode!

代替/ test路径上的env调用,并在

处获得一个漂亮的空白页面
http://localhost:9292/test

一些博主表示,没有很多关于监狱长的文件,但我不同意。有一个完整的维基。见https://github.com/hassox/warden/wiki

慢慢来,了解如何在Rack中使用中间件。这是一篇非常好的文章https://blog.engineyard.com/2015/understanding-rack-apps-and-middleware

我想也许你可能想开始测试,因为我找到了一个很好的例子,你可以在你的应用中使用它。

ENV['RACK_ENV'] = 'test'
require 'test/unit'
require 'rack/test'

require File.dirname(__FILE__) + '/web'

class AuthenticationTest < Test::Unit::TestCase
  include Rack::Test::Methods

  def app
    WardenTest #MyApp
  end

  def test_without_authentication
    get '/protected'
    assert_equal 401, last_response.status
  end

  def test_with_bad_credentials
    authorize 'bad', 'boy'
    get '/protected'
    assert_equal 401, last_response.status
  end

  def test_with_proper_credentials
    authorize 'admin', 'admin'
    get '/protected'
    assert_equal 200, last_response.status
    assert_equal "You're welcome, authenticated client", last_response.body
  end
end

然后将几条路线添加到您的应用中。

helpers do
  def protected!
    return if authorized?
    headers['WWW-Authenticate'] = 'Basic realm="Restricted Area"'
    halt 401, "Not authorized\n"
  end

  def authorized?
    @auth ||=  Rack::Auth::Basic::Request.new(request.env)
    @auth.provided? and @auth.basic? and @auth.credentials and     
    @auth.credentials == ['admin', 'admin']
  end
end

get '/' do
  "Everybody can see this page"
end

get '/protected' do
  protected!
  "You're welcome, authenticated client"
end 

根据我使用Ruby的经验,开始测试任何新项目总是一个好主意。我经常先测试一些小块,但只是为了了解它们是如何工作的。

一旦你更好地了解Rack,特别是Rack :: Builder,你可以使用

map '/test' do
  ...all the middleware needed
  run App
end

尝试不同的配置,看看哪些最适合您的需求,就像我写这篇文章时那样。

享受! ; - )