2

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

我尝试使用sinatra_warden gem,但它也有自己的错误(可能与这个有关)。

配置.ru:

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

网络.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

版本:

  • 西纳特拉:1.1.0
  • 典狱长:1.2.1
  • 机架:1.4.1
  • 红宝石:1.9.3p194
  • 工头:0.60.0

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

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

4

2 回答 2

4

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
于 2012-11-06T03:49:45.810 回答
1

在您的 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

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

享受!;-)

于 2015-08-18T11:50:49.303 回答