Sinatra: проверка к...
 
Уведомления
Очистить всё

Sinatra: проверка ключа API скопирована в тридцать роутов. Как вынести?

4 Сообщения
4 Пользователи
2 Реакции
330 Просмотры
GoshaFedorov
Сообщения: 3
Автор темы
Пишет в irb тимлид
Присоединился: 3 месяца назад
[#121]

Я в Ruby недавно, до этого долго писал на Java. Достался внутренний сервис на Sinatra, Ruby 4.0, около тридцати роутов под /api, и в каждом две одинаковые строки проверки ключа:

get "/api/orders" do
  token = request.env["HTTP_AUTHORIZATION"].to_s.delete_prefix("Bearer ")
  halt 401, json(error: "unauthorized") unless ApiKey.active.exists?(token: token)

  json Order.recent.limit(50).as_json
end

post "/api/orders" do
  token = request.env["HTTP_AUTHORIZATION"].to_s.delete_prefix("Bearer ")
  halt 401, json(error: "unauthorized") unless ApiKey.active.exists?(token: token)

  # ...
end

В Spring я бы повесил фильтр, а тут как принято? Rails не предлагать, сервис маленький и пусть таким остаётся)


3 ответа
viktor.petrov
Сообщения: 26
Читает чужие PR бэкенд-разработчик
Присоединился: 4 года назад

В Sinatra для этого есть before с шаблоном пути и helpers. Фильтр выполняется до любого роута под /api, а хелпер доступен в самих роутах, если нужно знать, чей это ключ:

require "digest"

helpers do
  def current_api_key
    @current_api_key ||= begin
      token = request.env["HTTP_AUTHORIZATION"].to_s.delete_prefix("Bearer ")
      ApiKey.active.find_by(token_digest: Digest::SHA256.hexdigest(token))
    end
  end
end

before "/api/*" do
  halt 401, json(error: "unauthorized") unless current_api_key
end

get "/api/orders" do
  json Order.recent.limit(50).as_json
end

Заодно я поменял поиск на хэш ключа. Хранить ключи в базе открытым текстом не стоит: утечёт дамп, утекут и ключи. Если у вас пока так, это отдельная миграция, но сделать её стоит.


Ответ
alisher1996
Сообщения: 6
Пишет в irb архитектор
Присоединился: 3 года назад

Если сервис вырастет, посмотри на Roda: там проверку ставят один раз на ветку r.on "api". Но ради одного фильтра переезжать не стоит


Ответ
Лариса 2002
Сообщения: 9
Разобрался с блоками тимлид
Присоединился: 3 месяца назад

И сразу тест на запрос без заголовка, одна строчка. Если кто-то потом случайно сломает фильтр, это будет видно в CI, а не в проде


Ответ