Я прочитал это сообщение https://nvisium.com/blog/2014/ 09/10 /standing-protectfromforgery / и, если я правильно понял, по умолчанию в Rails 3, если у нас есть контроллер, который выглядит так:

class ApplicationController < ActionController:Base
  protect_from_forgery
end

Что в конечном итоге произойдет, так это то, что (в случае злоумышленника) сеанс будет уничтожен. Это означало бы, что если мы делаем что-то вроде проверки подлинности пользователя, поскольку сеанса не будет, запрос остановится.

Итак, мой вопрос, я считаю, что это:

class ApplicationController < ActionController:Base
  protect_from_forgery
  before_action :authenticate_user

  private

  def authenticate_user
    raise NotAuthenticated unless session.key?(:user)
  end
end

Это правильный способ сделать это вместо

class ApplicationController < ActionController:Base
  before_action :authenticate_user
  protect_from_forgery

  private

  def authenticate_user
    raise NotAuthenticated unless session.key?(:user)
  end
end

Другими словами, protect_from_forgery должно быть первым, что мы делаем в контроллере.

Верны ли мои предположения, или мне что-то не хватает в том, как порядок операций работает в контроллере?

2
Hommer Smith 2 Авг 2017 в 03:08

1 ответ

Лучший ответ

Порядок этих двух методов не важен, нет.

Причина связана с когда эти методы выполняются: это методы уровня класса, которые выполняются в контексте самого класса, когда Ruby загружает файл.

Посмотрите на источник для protect_from_forgery:

def protect_from_forgery(options = {})
  options = options.reverse_merge(prepend: false)

  self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)
  self.request_forgery_protection_token ||= :authenticity_token
  before_action :verify_authenticity_token, options
  append_after_action :verify_same_origin_request
end

По сути, это макросы, которые добавляют код к вашему классу при их вызове, форма метапрограммирования. Вы можете заменить вызов метода в классе настройкой этих параметров вручную, и все будет так же.

Все это происходит, когда ваш код загружается впервые, до загрузки приложения.

3
Adam Lassek 2 Авг 2017 в 03:14
Спасибо за ответ. Я до сих пор не понимаю, как это будет работать, если я хочу сначала выполнить protect_from_forgery, а затем проверить что-либо в сеансе. Если я сделаю наоборот, удаление сеанса не имеет значения, потому что злоумышленник уже мог его использовать.
 – 
Hommer Smith
2 Авг 2017 в 04:07
Защита от подделки и проверка подлинности пользователя - это разные задачи. Неважно, в каком порядке вы их выполняете, потому что неважно, что это произойдет до того, как на запрос будет дан ответ.
 – 
Adam Lassek
2 Авг 2017 в 04:32
Я понимаю, что они произойдут до того, как будет дан ответ на запрос. Однако, если аутентификация пользователя происходит до защиты от подделки (когда сессия удаляется), мы будем думать, что пользователь аутентифицирован правильно, потому что, когда она была достигнута, у нас все еще был сеанс. Имеет смысл?
 – 
Hommer Smith
2 Авг 2017 в 05:40
Если сеанс удален во время ответа, он будет вести себя так, как если бы пользователь не прошел проверку подлинности. Пока возможности использовать сеанс нет. По крайней мере, так оно и должно работать, поскольку вы не предоставили никакого кода аутентификации, я могу говорить только в общих чертах.
 – 
Adam Lassek
2 Авг 2017 в 05:47
Я добавил фиктивный код, чтобы выразить то, что имел в виду. Это не обязательно связано с аутентификацией, для меня это любой код, который будет полагаться на сеанс. Если мы удалим сеанс ПОСЛЕ того, как он был использован, у нас могут возникнуть проблемы. Вот почему я ожидал, что protect_from_forgery должно быть первым, что нужно выполнить перед любым действием в контроллере.
 – 
Hommer Smith
2 Авг 2017 в 05:56