Ruby 1.9.2 + Sinatra - 需要在某些路由上进行身份验证

时间:2011-10-24 13:00:59

标签: ruby authentication sinatra aop

在开始之前,这基本上是对Sinatra的现有ASP.MVC REST样式服务的端口。我是Ruby的新手,所以还没有真正了解最佳实践,而且网络似乎对这个问题有点不了解。

所以目前在ASP风格中我们有一些像这样的控制器:

public class MyController : Controller
{
    [Authenticate]
    public ActionResult AccessSecretStuffs()
    {...}

    public ActionResult AccessPublicStuffs()
    {...}
}

现在我们使用过滤器来确保在加载操作之前,使用Authenticate的任何操作都会检查当前用户的身份验证。这些路线设置相当普遍,它们只是映射到控制器和操作。

现在在使用Sinatra的Ruby土地上你不会有控制器,一切都是动作,而且我们纯粹希望以一种宁静的方式公开数据,这看起来很棒。但是我需要能够确保每当使用Sinatra调用某些路由时,它将首先调用一些代码来检查它们是否可以访问该操作,然后如果不将它们重定向到登录页面。

我当时正考虑加入一些AOP来解决这个问题,但经过一番阅读后,所有人都说Ruby不需要AOP,并且已经提供了大部分功能。那么,任何人都可以对这样做的最佳实践有所了解吗?

Sinatra文档有一个适用的before方法,但是我需要为每个其他路由方法做一个before方法,这不是理想的。在我看来,我只是想声明一个路线,然后在末尾添加一些注释/属性,表明需要发生的事情......

希望这有点道理:)

1 个答案:

答案 0 :(得分:3)

Ruby没有这样的注释,但Sinatra确实提供了自定义过滤机制。

定义路径时,可以添加其他条件,例如各种标题值等等。您还可以定义自定义条件:

set(:auth) do |*roles|   # <- notice the splat here
    condition do
        unless logged_in? && roles.any? {|role| current_user.in_role? role }
            redirect "/login/", 303 
        end
    end
end

然后你可以定义这样的路线:

get "/secret", :auth => [:user, :admin] do
    ...
end

或者如果您不需要传递任何参数,则在block之前可以将路径作为参数:

before '/secret/*' do
    authenticate!
end

您可以在Sinatra readme page

了解更多信息