我有一个简单的 Sinatra 应用程序,带有两个控制器和 api 助手
# ApplicationController
class ApplicationController < Sinatra::Base
register Sinatra::ActiveRecordExtension
helpers ApiHelper
configure :production, :development do
enable :logging
end
before do
content_type :json
end
get '/hello' do
{ message: 'Hello!' }.to_json
end
end
# ArticlesController
class ArticlesController < ApplicationController
before do
authenticate!
end
get '/articles' do
articles = Article.all
articles.map { |article| serialize(article) }
end
...
end
# ApiHelper
module ApiHelper
def authenticate!
halt 403, { message: 'Unauthorized!' }.to_json unless authorized?
end
private
def authorized?
request.env['HTTP_AUTHORIZATION'] == 'Bearer 123qweasd'
end
end
当我做
curl -X GET -i -H 'Accept: application/json' http://localhost:4567/hello
做健康检查我得到 403 Unauthorized
。为什么?我不需要在 /hello
端点中进行身份验证,只需要在 /articles
CRUD 端点中进行身份验证,所以我不明白为什么它在 /hello
中进行身份验证。根据文档 before
块用于在其他操作运行之前执行某些操作,但我不会在 authenticate!
中的 before
块中调用 ApplicationController
。我错过了什么?
如果你想要求对除 /hello 端点之外的所有端点进行身份验证,你可以修改你的身份验证!方法仅在当前端点不是 /hello 时才需要身份验证,如下所示:
module ApiHelper
def authenticate!
halt 403, { message: 'Unauthorized!' }.to_json unless authorized? || request.path_info == '/hello'
end
...
end
这将允许对 /hello 端点的请求绕过身份验证检查。
或者:
你可以移动身份验证!方法仅适用于 ArticlesController,并将其从 ApiHelper 模块中删除。然后,您可以仅在 ApplicationController 中包含 ApiHelper 模块,如下所示:
# ArticlesController
class ArticlesController < ApplicationController
before do
authenticate!
end
get '/articles' do
articles = Article.all
articles.map { |article| serialize(article) }
end
private
def authenticate!
halt 403, { message: 'Unauthorized!' }.to_json unless authorized?
end
def authorized?
request.env['HTTP_AUTHORIZATION'] == 'Bearer 123qweasd'
end
end
# ApiHelper
module ApiHelper
def serialize(object)
# ... same as before ...
end
end
不清楚为什么你的 before
中的 ArticlesController
块似乎适用于 /hello
中的 ApplicationController
端点。上面定义的方法将使 /hello
动作不可能受到 authenticate
方法的影响,因为我们确保它甚至没有被定义。这可能不是理想的,但它可能有助于解决在向 authenticate!
.
/hello
方法的任何问题