Strong parameters w Rails 4

W wersji 4 Railsów wprowadzono coś takiego jak: permit_params.
Przeczytałem o tym tutaj, ale nadal nie bardzo rozumiem idee (sens istnienia) takiej konstrukcji
http://guides.rubyonrails.org/action_controller_overview.html

W Rails 3 dało się zrobić np. tak:

def create
  Post.create(params[:title])
end

Próbowałem podobnej konstrukcji w Rails 4, ale nie przeszło :smile:
Więc z Guidem przerobiłem kod na coś takiego:

 def create
    Post.create(post_params)
end

private

def post_params
  params.require(:post).permit(:title)
end

Sęk w tym, że nie bardzo rozumiem ten zapis. Co się dzieje pod maską? I właściwie po co coś takiego? Jaka bya wada tego prostego rozwiązania w Rails 3?

W rails 3 było coś takiego jak attr_accessible i atrybuty, które chciałeś ustawić za pomocą hasha musiałeś umieszczać w attr_accessible, co uniemożliwiało ustawienie (np. z poziomu konsoli) pozostałych atrybutów za pomocą hasha (mass assignment).

Tak samo, z różnych kontrolerów teoretycznie można by ustawić różne parametry/atrybutów konkretnego modelu, np. różny poziom dostęp itd, a ustawiając attr_accessible ustawiasz tak jakby globalnie (dla konkretnego modelu) co można ustawić przez mass assignment a czego nie można.

1 Like

Cały ten mechanizm jest po to, aby programista sam decydował jakie parametry są dopuszczalne. Gdyby nie było nic takiego, ktoś mógłby przykładowo zmodyfikować sobie formularz Firebugiem i przesłać dodatkowy (niebezpieczny) parametr typu user_id, password i tym podobne i w ten sposób namieszać nam w bazie dosyć konkretnie. Swojego czasu miał z tym problem m.in github.

Dlatego w Rails 3 wprowadzono coś takiego jak attr_attributes, gdzie na poziomie modelu to deklarowałeś, co dalej wiązało się z wieloma problemami, bo było to globalne per model.

Strong parameters pozwala na definiowanie akceptowanych parametrów per akcja/kontroler, co daje już pełną swobodę i bezpieczeństwo. A to, że trzeba napisać kilka linijek więcej… cóż, coś za coś :slight_smile:

Edit: Wolniejszy byłem :wink:

1 Like

Teraz rozumiem iee. Dzięki Wam obu za odpowiedzi :slight_smile:

Faktycznie nie pomyślałem, że ktoś złośliwy łatwo mógłby namieszeć bez takiego mechanizmu.

[ciekawostka] Problemy z dozwolonymi atrybutami dotykały wszystkich, nawet githuba: http://web.archive.org/web/20130818070952/https://github.com/rails/rails/issues/5239 (link do web archive bo potem ręcznie zmieniono datę :slight_smile: ) [/ciekawostka]

Jeszcze przyszło mi do głowy takie pytanie.
Jak to jest z:

def edit
  @post = Post.find(params[:id])
end

Taki zapis przechodzi w Rails 4. Czy to dotyczy jakiejś konwencji, że po prostu :id jest zaufanym symbolem tutaj?
Tak wnioskuje z tego co wyczytałem tu: http://guides.rubyonrails.org/action_controller_overview.html :smiley:

Czy są jeszcze jakieś inne domyślne “bezpieczne” parametry?

To nie kwestia tego, że parametrem jest :id, a że metodą jest .find. W tym przypadku nie ma problemu z mass assignment - nikt nie jest w stanie ci zmienić niczego w bazie poprzez find (o ile nie ma problemu z SQL injection, ale to inna bajka). Zabezpieczenia przed mass assignment sprawdzają metody zmieniające atrybuty modelu - np. .create, #attributes=, #update, etc.

1 Like

Zerknij na https://github.com/hashrocket/decent_exposure - strasznie ułatwia mi pracę. :wink: