从Sinatra中的全局身份验证中排除某些路径

时间:2014-09-01 11:02:32

标签: ruby authentication sinatra

我在Sinatra中有一个API,使用中间件使用令牌进行全局限制身份验证。 此中间件在before语句中插入身份验证检查,以便全局保护所有内容,而无需在每个路由定义中添加检查。

before do
  denied unless
    authorized? or
    env['PATH_INFO'] == '/auth/login' or
    env['REQUEST_METHOD'] == 'OPTIONS' # For AngularJS headers checks
end

但是现在我有一些路线需要从这个全局限制中排除(只有2或3个数十个)并且不知道如何做到这一点。

我首先想到的是Sinatra条件:http://www.sinatrarb.com/intro.html#Conditions但是因为它在之前的陈述中,我以前无法采取行动来避免这种情况。

然后我找到了这个解决方案:Before filter on condition

但它并不是一个干净的方式,它不适用于中间件和模块化Sinatra应用程序。

所以经过大量搜索后,我需要一些帮助和建议。

如何做到这一点,可能是我的中间件中有助手,条件和一些修改?

1 个答案:

答案 0 :(得分:4)

为什么不将不需要授权的路由列表放入数组并进行检查?

configure do
  set :no_auth_neededs, ['/auth/login', "/a", "/b", "/c"]
end

before do
  denied unless
    authorized? or
    settings.no_auth_neededs.include?(env['PATH_INFO']) or
    env['REQUEST_METHOD'] == 'OPTIONS' # For AngularJS headers checks
end

我没有测试过这个。


更新

我还有另外两种方式可以想到这样做,我的懒惰不会抱怨,如果我花了10秒的思考时间......但我很高兴相信直觉:)

扩展DSL

写一个authorised_route处理程序:

require 'sinatra/base'

module Sinatra
  module AuthorisedRoute
    def authorised_route(verb,path,&block)
      before path do
        denied unless
          authorized? or
          request.request_method == 'OPTIONS' # For AngularJS headers checks
      end
      send verb.to_sym, path, &block
    end
  end

  register AuthorisedRoute
end

class API < Sinatra::Base
  register AuthorisedRoute

  authorised_route "get", "/blah" do
    # blah
  end

  get "/free-route" do
    # blah
  end
end

您可以删除before块,然后将逻辑放在路径YMMV中。有很多方法可以使用这种东西。请注意将env替换为request(请参阅Accessing the Request Object

See the docs for more on DSL extensions

使用班级

分离出两种类型的路由,即类的用途,共享属性和/或行为的事物组:

require 'sinatra/base'

class AuthedAPI < Sinatra::Base

  before do
    denied unless
      authorized? or
      request.request_method == 'OPTIONS' # For AngularJS headers checks
  end

  # you should probably add the `denied` and `authorized?` helpers too

  # list of routes follow…
end

# define route that don't need auth in here
class OpenAPI < Sinatra::Base
  get "/auth/login" do
    # stuff…
  end
end

class API < Sinatra::Base
  use OpenAPI  # put OpenAPI first or a `denied` will happen.
  use AuthedAPI
end

然后将API映射到"/"(或无论API的根路径是什么)在rackup文件中。只有AuthedAPI中的路由才会受before阻止。