【问题标题】:Ruby 1.9.2 + Sinatra - Requiring authentication on certain routesRuby 1.9.2 + Sinatra - 要求对某些路由进行身份验证
【发布时间】:2023-04-08 19:53:02
【问题描述】:

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

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

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

    public ActionResult AccessPublicStuffs()
    {...}
}

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

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

我本来想加入一些 AOP 来解决这个问题,但是在阅读了一些之后,每个人都说 Ruby 不需要 AOP,并且已经提供了开箱即用的大部分功能。那么任何人都可以阐明执行此操作的最佳实践吗?

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

希望这有某种意义:)

【问题讨论】:

    标签: ruby authentication sinatra aop


    【解决方案1】:

    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
    

    或者如果你不需要传递任何参数, before block 可以将路径作为参数:

    before '/secret/*' do
        authenticate!
    end
    

    您可以在Sinatra readme page阅读更多内容

    【讨论】:

    • 我不敢相信我以前从未在自述文件中看到过这部分内容,感觉有点像个白痴……我只是试了一下,但如果我想要一个不带参数的自定义过滤器那看起来怎么样?即获取 "/secret", :auth do ... end
    • 没那么简单。从技术上讲,get 的第二个参数是条件映射,所以你需要在:auth =&gt; nil 行做一些事情
    • 您实际上可以将这种方法与get "/secret", protected: true do一起使用
    猜你喜欢
    • 2013-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 2021-10-18
    • 2014-10-25
    • 1970-01-01
    • 2014-04-04
    相关资源
    最近更新 更多