Django, formularze i modele, autentykacja
Transkrypt
Django, formularze i modele, autentykacja
Zaawansowany kurs języka Python Środowisko Django, cz. 3 Marcin Młotkowski 22 stycznia 2015 Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Plan wykładu 1 Formularze dla modeli Konstrukcja formularzy Walidacja i zapis 2 Testowanie Testy jednostkowe Symulowanie klienta 3 Implementacja autentykacji Autentykacja Ograniczenie dostępu 4 Uzupełnienie Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Plan wykładu 1 Formularze dla modeli Konstrukcja formularzy Walidacja i zapis 2 Testowanie Testy jednostkowe Symulowanie klienta 3 Implementacja autentykacji Autentykacja Ograniczenie dostępu 4 Uzupełnienie Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Przykładowa aplikacja System Zapisy, modele Wykladowca Student Wyklad Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Przypomnienie Modele Typy danych. Co można robić z wartościami zapamiętywanie/odtwarzanie edycja/tworzenie Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Edycja wartości ręczne zbudowanie formularza w html’u; zdefiniowanie obiektu (pod)klasy forms.Form; skorzystanie z klasy dedykowanej. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Konstrukcja formularzy dla modeli from django.forms import ModelForms from wyklad.zapisy.models import Wyklad class WykladForm: class Meta: model = Wyklad fields = [’tytul’, ’opis’, ’ects’] Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Co mamy w wyniku model class Wyklad(models.Model): nazwa = models.CharField(max length=140) ects = models.IntegerField() wykladowca = models.ForeignKey(Wykladowca) Ręczny formularz class WykladForm(forms.Form): nazwa = forms.CharField(max length=140) ects = forms.IntegerFields() wykladowca = forms.ModelChoiceField(queryset=Wykladowca.objects.all()) Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Definiowanie pól do edycji: uzupełnienie Edycja wszystkich pól class WykladForm: class Meta: model = Wyklad fields = [’ all ’] Zmiana domyślnych ustawień class WykladForm: class Meta: model = Wyklad fields = [’tytul’, ’opis’] widgets = { ’opis’ : Textarea(attrs={’cols’: 80, ’rows’: 20}} } Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Przypomnienie ModelForm.is valid() Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Zapis danych Obiekty klasy ArticleForms implementują metodę save() Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Scenariusze Nowy obiekt w = WykladForm(request.POST) nowy wyklad = w.save() Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis Scenariusze Nowy obiekt w = WykladForm(request.POST) nowy wyklad = w.save() Istniejący obiekt w = Wyklad.objects.get(id=13) w = WykladForm(request.POST, instance=w) nowy wyklad = w.save() Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Konstrukcja formularzy Walidacja i zapis .save() waliduje formularz. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Plan wykładu 1 Formularze dla modeli Konstrukcja formularzy Walidacja i zapis 2 Testowanie Testy jednostkowe Symulowanie klienta 3 Implementacja autentykacji Autentykacja Ograniczenie dostępu 4 Uzupełnienie Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Poziomy testowania Testy jednostkowe Patrz: wykład 9: unittest Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Poziomy testowania Testy jednostkowe Patrz: wykład 9: unittest Testy klienckie Symulacja działania przeglądarki. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Mała sugestia Zamiast import unittest lepiej from django.test import TestCase Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Różnice między unittest a django.test automatyczne ładowanie danych testowych do bazy testowej; Każdy test jest odrębną transakcją; dodatkowe asercje do testowania HTML’a, przekierowań HTTP, etc. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Przykład from django.test import TestCase from wyklad.zapisy.models import Wyklad class WykladTestCase(TestCase): def setUp(self): Wyklad.objects.create(nazwa=’Python’, ects=3) def test zapisu(self): py = Wyklad.objects.get(nazwa=’Python’) self.assertEqual(py.ects, 3) Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Przykład from django.test import TestCase from wyklad.zapisy.models import Wyklad class WykladTestCase(TestCase): def setUp(self): Wyklad.objects.create(nazwa=’Python’, ects=3) def test zapisu(self): py = Wyklad.objects.get(nazwa=’Python’) self.assertEqual(py.ects, 3) ./manage.py test Wyszukuje wszystkie pliki test*.py i traktuje je jako elementy zestawu testów. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Testowa baza danych Testowa baza danych (test baza produkcyjna ) jest czyszczona po każdym teście. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Dane testowe Dane testowe z istniejącej bazy danych: manage.py syncdb tworzy plik initial data z danymi Te dane są domyślnie ładowane podczas testów. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Inne dane testowe from django.test import TestCase from wyklad.zapisy.models import Wyklad class WykladTestCase(TestCase): fixtures = [’jesien.json’, ’wiosna’] ... Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Klient testowy django.test.client.Client Symuluje wysyłanie zapytań GET/POST. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Klient testowy django.test.client.Client Symuluje wysyłanie zapytań GET/POST. Można też używać narzędzi typu Selenium. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Przykład scenariusza from django.test.client import Client student = Client() response = student.post(’/login/’, {’username’: ’i123456’, ’password’: ’123456’}) print response.status code # 200 response = student.get(’/student/profil/’) print response.content Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Uwagi Scenariusze można opakować w przypadki testowe i korzystać z dodatkowych asercji z django.test.TestCase Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Testy jednostkowe Symulowanie klienta Uwagi Scenariusze można opakować w przypadki testowe i korzystać z dodatkowych asercji z django.test.TestCase django dostarcza specjalizowanych klas do implementacji różnych testów wraz z sugestiami w jakich sytuacjach ich używać. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Plan wykładu 1 Formularze dla modeli Konstrukcja formularzy Walidacja i zapis 2 Testowanie Testy jednostkowe Symulowanie klienta 3 Implementacja autentykacji Autentykacja Ograniczenie dostępu 4 Uzupełnienie Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Autentykacja django oferuje domyślnie system użytkowników; system uprawnień; formularze i widoki do logowania. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Użytkownicy Utworzenie użytkowników Z panelu administracyjnego Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Użytkownicy Utworzenie użytkowników Z panelu administracyjnego podstawowe atrybuty modelu User username password email first name, last name Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Hasła Hasła są przechowywane w postaci hasza, z losową solą i informacją o algorytmie haszowania. Zmiana hasła user = User.objects.get(...) user.set password(’noweHaslo’) user.save() Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Weryfikacja użytkownika Autentykacja from django.contrib.auth import authenticate user = authenticate(username=’mm’, password=’123456’) if user is not None: ... Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Weryfikacja użytkownika Autentykacja from django.contrib.auth import authenticate user = authenticate(username=’mm’, password=’123456’) if user is not None: ... Weryfikacja if request.user.is authenticated(): # zrób coś else : # anonimowy użytkownik Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu logowanie Autentykacja tylko weryfikuje, ale nie tworzy sesji dla użytkownika. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu logowanie Autentykacja tylko weryfikuje, ale nie tworzy sesji dla użytkownika. from django.contrib.auth import authenticate, login def login view(request): username = request.POST[’username’] password = request.POST[’password’] user = authenticate(username=username, password=password) if user is not None: if user.is active: login(request, user) # Przekieruj na odpowiednią stronę. else : # informacja o zablokowanym koncie else : # Zgłoś błąd logowania. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Wylogowanie from django.contrib.auth import logout def logout view(request): logout(request) Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Rozwiązanie proste from django.shortcuts import redirect def tajne view(request): if not request.user.is authenticated(): return redirect(’/login/?next=%s’ % request.path) Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Inne rozwiązanie wersja z dekoratorem from django.contrib.auth.decorators import login required @login required def tajne view(request): W razie braku autentykacji przekierowuje na stronę określoną w settings.LOGIN URL. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Dodatkowe domyślne mechanizmy system grup użytkowników; system uprawnień. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Autentykacja Ograniczenie dostępu Na koniec Czego nie ma w standardowym django sprawdzanie siły hasła wsparcie dla innych systemów użytkowników; ograniczenie prób nieudanego logowania. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Plan wykładu 1 Formularze dla modeli Konstrukcja formularzy Walidacja i zapis 2 Testowanie Testy jednostkowe Symulowanie klienta 3 Implementacja autentykacji Autentykacja Ograniczenie dostępu 4 Uzupełnienie Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Hosting Django www.heroku.com: hobbistyczne projekty: free, obsługa Ruby, Java, Scala, Python, Django, ... www.pythonanywhere.com: od 0$/miesiąc; www.webfaction.com: Django, PHP, Perl, Rails, ... https://www.linode.com/: Linux na wirtualnej maszynie Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Hosting Django www.heroku.com: hobbistyczne projekty: free, obsługa Ruby, Java, Scala, Python, Django, ... www.pythonanywhere.com: od 0$/miesiąc; www.webfaction.com: Django, PHP, Perl, Rails, ... https://www.linode.com/: Linux na wirtualnej maszynie http://djangohosting.com/ Strona z odnośnikami do Djangowych hostingów z komentarzami. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Mechanizmy bezpieczeństwa domyślny HTML escaping Zamiana tagów html w szablonach: < na < > na > ’ na ' & na & Użycie HTTPS zamiast HTTP Trzymanie plików źródłowych poza katalogiem udostępnionym serwerowi WWW. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Cross site scripting (XSS) Opis ataku Osadzenie obcego kodu (np. JavaScript) na stronach WWW; przykładowo wklejając ten kod jako komentarz na forum. Obrona HTML escaping, ale nie obroni przed wszystkimi atakami. Ostrożność przy zapamiętywaniu obcego html’u. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Cross site request forgery (CSRF) Opis ataku Nieświadome wykonanie akcji wymagającej uprawnień, np. poprzez kliknięcie na spreparowany link. Obrona Dodanie do formularzy ukrytego pola z losowym tokenem: <form action="." method="post">{% csrf_token %} i zabezpieczenie widoku from django.views.decorators.csrf import csrf protect from django.shortcuts import render @csrf protect def widok(request): Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie SQL injection Opis ataku Wstrzyknięcie obcego kodu do zapytania SQL Obrona Standardowo zapytania SQL są zabezpieczane poprzez dodanie ukośników przed znakami specjalnymi. Marcin Młotkowski Zaawansowany kurs języka Python Formularze dla modeli Testowanie Implementacja autentykacji Uzupełnienie Clickjacking Opis ataku Oryginalna strona jest w sposób ukryty osadzana jako ramka na stronie na złośliwym serwerze. Obrona Zakazanie osadzania strony poprzez dodaniu taga X-Frame-Options: deny w odpowiedzi serwera: X_FRAME_OPTIONS = ’DENY’ Marcin Młotkowski Zaawansowany kurs języka Python