Szukam sugestii dotyczących budowy bezpiecznego REST API w Ruby on Rails

Zaczynam budować REST API dla projektu, nad którym pracuję, i doprowadziło mnie to do zrobienia trochę badań nad najlepszym sposobem zbudowania API przy użyciu RoR. Dość szybko dowiaduję się, że domyślnie modele są otwarte na świat i można je nazwać przez URL, po prostu umieszczając".xml " na końcu adresu URL i przekazując odpowiednie parametry.

Więc przyszło następne pytanie. Jak zabezpieczyć aplikację, aby zapobiec nieautoryzowanym zmianom? W trakcie badań znalazłem kilka artykułów mówiąc o attr_accessible i attr_protected i jak można ich używać. Konkretny adres URL, który znalazłem, mówiący o nich, został opublikowany w maju 2007 (tutaj ).

Jak w przypadku wszystkich rzeczy ruby, jestem pewien, że rzeczy ewoluowały od tego czasu. Więc moje pytanie brzmi, czy to nadal najlepszy sposób, aby zabezpieczyć REST API w RoR?

Jeśli nie co sugerujesz w scenariuszu" nowego projektu "lub"istniejącego projektu"?

Author: Mechanical snail, 0000-00-00

4 answers

Istnieje kilka schematów uwierzytelniania żądań API i różnią się one od normalnego uwierzytelniania dostarczanego przez wtyczki, takie jak restful_authentication lub acts_as_authenticated. Co najważniejsze, klienci nie będą utrzymywać sesji, więc nie ma koncepcji logowania.

Uwierzytelnianie HTTP

Możesz użyć podstawowego uwierzytelniania HTTP. W tym celu klienci API będą używać zwykłej nazwy użytkownika i hasła i po prostu umieszczać je w adresie URL w następujący sposób:

http://myusername:[email protected]/

I uwierz, że restful_authentication obsługuje to po wyjęciu z pudełka, więc możesz zignorować to, czy ktoś używa Twojej aplikacji za pośrednictwem API lub przeglądarki.

Jedną z wad jest to, że prosisz użytkowników o podanie nazwy użytkownika i hasła w każdym zapytaniu. Robiąc to przez SSL, możesz to zabezpieczyć.

Wydaje mi się, że nigdy nie widziałem API, które tego używa. Wydaje mi się to przyzwoicie dobrym pomysłem, zwłaszcza, że jest wspierany po wyjęciu z pudełka przez obecne Schematy uwierzytelniania, więc nie wiem w czym problem.

Klucz API

Innym łatwym sposobem włączenia uwierzytelniania API jest użycie kluczy API. Zasadniczo jest to nazwa użytkownika usługi zdalnej. Gdy ktoś zarejestruje się, aby korzystać z twojego API, dajesz mu klucz API. To musi być przekazywane z każdym żądaniem.

Jedną z wad jest to, że jeśli ktoś dostanie klucz API kogoś innego, może składać wnioski jako ten użytkownik. Myślę, że poprzez składanie wszystkich zapytań API użyj HTTPS (SSL), możesz nieco zrównoważyć to ryzyko.

Kolejną wadą jest to, że użytkownicy używają wszędzie tych samych poświadczeń uwierzytelniania (klucza API). Jeśli chcą odwołać dostęp do klienta API, ich jedyną opcją jest zmiana klucza API, co spowoduje wyłączenie wszystkich innych klientów. Można to złagodzić, umożliwiając użytkownikom generowanie wielu kluczy API.

API Key + Secret Key signing

Deprecated ( rodzaj) - patrz OAuth poniżej

Znacznie bardziej skomplikowane jest podpisanie żądania tajnym kluczem. To właśnie robią Amazon Web Services (S3, EC2 i takie tam). Zasadniczo dajesz użytkownikowi 2 klucze: klucz API (np. nazwa użytkownika) i ich tajny klucz (tj. hasło). Klucz API jest przesyłany z każdym żądaniem, ale tajny klucz nie jest. Zamiast tego jest używany do podpisywania każdego żądania, zwykle przez dodanie innego parametru.

IIRC, Amazon osiąga to, biorąc wszystkie parametry do żądania, i porządkowanie ich po nazwie parametru. Następnie łańcuch ten jest hashowany, używając tajnego klucza użytkownika jako klucza hashowego. Ta nowa wartość jest dołączana jako nowy parametr do żądania przed wysłaniem. Po stronie Amazona robią to samo. Pobierają wszystkie parametry (z wyjątkiem podpisu), porządkują je i hashują za pomocą tajnego klucza. Jeśli to pasuje do podpisu, wiedzą, że żądanie jest uzasadnione.

Minusem jest tutaj złożoność. Doprowadzenie tego schematu do poprawnego działania to ból, zarówno dla programisty API i klientów. Spodziewaj się wielu połączeń z Pomocą techniczną i wściekłych e-maili od programistów klientów, którzy nie mogą uruchomić rzeczy.

OAuth

Aby zwalczyć niektóre problemy ze złożonością klucza + tajnego podpisywania, pojawił się standard o nazwie OAuth . OAuth jest odmianą klucza + tajnego podpisywania, ale wiele z nich jest znormalizowanych i zostało włączone do bibliotek dla wielu języków.

Ogólnie rzecz biorąc, jest to znacznie łatwiejsze w obu producent API i konsument do korzystania z OAuth zamiast tworzenia własnego systemu klucza / podpisu.

OAuth również z natury segmentuje dostęp, zapewniając różne poświadczenia dostępu dla każdego konsumenta API. Umożliwia to użytkownikom selektywne cofanie dostępu bez wpływu na inne zużywające się aplikacje.

Specjalnie dla Ruby, istnieje OAuth gem , który zapewnia wsparcie zarówno dla producentów, jak i konsumentów OAuth. Użyłem tego klejnotu do zbudowania API i również spożywać OAuth APIs i był pod wrażeniem. Jeśli uważasz, że Twoja aplikacja potrzebuje OAuth (w przeciwieństwie do prostszego schematu klucza API), mogę z łatwością polecić użycie OAuth gem.

 102
Author: Micah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-26 19:04:21

Jak zabezpieczyć moją aplikację, aby zapobiec nieautoryzowane zmiany?

attr_accessible i attr_protected są przydatne do kontrolowania zdolności do wykonywania zadań masowych na modelu ActiveRecord. Zdecydowanie chcesz użyć attr_protected, aby zapobiec atakom form injection; zobacz Użyj attr_protected, albo cię zhakujemy .

Ponadto, aby uniemożliwić komuś dostęp do kontrolerów w Twojej aplikacji Rails, prawie na pewno będziesz potrzebował jakiegoś użytkownika System Uwierzytelniania i umieść before_filter w kontrolerach, aby upewnić się, że masz autoryzowanego użytkownika składającego żądanie, zanim zezwolisz na wykonanie żądanej akcji kontrolera.

Zobacz Ruby on Rails Security Guide (część projektu dokumentacji Rails), aby znaleźć wiele przydatnych informacji.

 7
Author: Gabe Hollombe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-29 19:28:48

Stoję przed podobnymi pytaniami jak ty w tej chwili, ponieważ buduję również REST api dla aplikacji rails.

Proponuję upewnić się, że tylko atrybuty, które mogą być edytowane przez użytkownika są oznaczone atrybutem attr_accessible. Spowoduje to utworzenie białej listy atrybutów, które można przypisać za pomocą update_attributes.

To co robię to coś takiego:

   class Model < ActiveRecord::Base  
       attr_accessible nil  
   end

Wszystkie moje modele dziedziczą z tego, więc są zmuszone zdefiniować attr_accessible dla dowolnych pól, które chcą dokonać przypisania masy. Osobiście żałuję, że nie ma sposobu, aby włączyć to zachowanie domyślnie(może być, a ja o tym Nie wiem).

Żebyś wiedział, że ktoś może masowo przypisać właściwość nie tylko za pomocą REST api, ale także za pomocą zwykłego formularza post.

 3
Author: jonnii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-29 15:06:42

Innym podejściem, które oszczędza budowanie wielu rzeczy samemu jest użycie czegoś takiego jak http://www.3scale.net / który obsługuje klucze, tokeny, kwoty itp. dla indywidualnych deweloperów. Zajmuje się również analityką i tworzy portal dla programistów.

Istnieje wtyczka ruby / rails ruby API plugin, która będzie miała zastosowanie do zasad dotyczących ruchu w miarę jego przybycia - możesz jej używać w połączeniu z OAuth gem. Można również nas GO upuszczając lakier przed aplikacją i użycie varnish lib mod: Varnish API Module .

 0
Author: steve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-03 12:55:04