【问题标题】:Unable to use Warden in Sinatra App: env['warden'] returns nil无法在 Sinatra 应用程序中使用 Warden:env['warden'] 返回 nil
【发布时间】:2012-11-06 00:33:59
【问题描述】:

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

我尝试使用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

config/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

版本:

  • 西纳特拉:1.1.0
  • 守望者:1.2.1
  • 机架:1.4.1
  • 红宝石:1.9.3p194
  • 工头:0.60.0

任何想法如何使用我描述的设置的守望者?

(PS 出于好奇,env 变量到底是什么?)

【问题讨论】:

    标签: ruby sinatra rack warden


    【解决方案1】:

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

    我相信您在config/warden.rb 中对use 的构建器调用会被忽略。从该文件中删除指令并将它们添加到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
    

    【讨论】:

    • 工作就像一个魅力!非常感谢:)
    • 哦对了,env变量代表请求环境;它基本上是您想了解的有关请求的所有内容的哈希(标头、请求方法、参数等)
    • 我同意使用 sinatra 文件或 rack 文件保留使用调用。 Sinatra 是基于 Rack 的,因此也包括 Rack。还有一个 gem 'sinatra-warden' 应该可以与这些网络应用程序的较新版本一起使用。刚刚在 8 月的这周学习或者只是发现了 sinatra 身份验证策略。 2015.
    【解决方案2】:

    在您的 config.ru 中添加指向您的配置/管理员的链接

    require File.dirname(__FILE__) + '/config/warden'
    

    阅读典狱长自述文件。或者直接在 lib/warden.rb 中查看

    我放了

    Warden.test_mode!
    

    代替 /test 路径中的 env 调用,并在以下位置获得一个漂亮的空白页

    http://localhost:9292/test
    

    一些博主表示没有很多关于warden 的文档,但我不同意。有一个完整的维基。见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
    

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

    享受吧! ;-)

    【讨论】:

      猜你喜欢
      • 2011-08-07
      • 1970-01-01
      • 1970-01-01
      • 2013-01-10
      • 2012-12-14
      • 2019-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多