bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


Barra lateral

ASIX Administració de Sistemes Informàtics i Xarxes
Tots els mòduls del cicle
MP01 Implantació de sistemes operatius
Totes les UFs del modul
MP02 Gestió de bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Fonaments de maquinari
Totes les UFs del modul
MP06 Administració de sistemes operatius
Totes les UFs del modul
MP07 Planificació i administració de xarxes
Totes les UFs del modul
MP08 Serveis de xarxa i Internet
Totes les UFs del modul
MP09 Implantació d'aplicacions web
Totes les UFs del modul
MP10 Administració de sistemes gestors de bases de dades
Totes les UFs del modul
MP11 Seguretat i alta disponibilitat
Totes les UFs del modul
MP12 Formació i orientació laboral
Totes les UFs del modul
MP13 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP14 Projecte
Totes les UFs del modul
DAM Desenvolupament d’aplicacions multiplataforma
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Accés a dades
Totes les UFs del modul
MP07 Desenvolupament d’interfícies
Totes les UFs del modul
MP08 Programació multimèdia i dispositius mòbils
Totes les UFs del modul
MP09 Programació de serveis i processos
Totes les UFs del modul
MP10 Sistemes de gestió empresarial
Totes les UFs del modul
MP11 Formació i orientació laboral
Totes les UFs del modul
MP12 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP13 Projecte de síntesi
Totes les UFs del modul
MPDual Mòdul Dual / Projecte
DAW Desenvolupament d’aplicacions web
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació
Totes les UFs del modul
MP04 Llenguatge de marques i sistemes de gestió d’informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Desenvolupament web en entorn client
Totes les UFs del modul
MP07 Desenvolupament web en entorn servidor
Totes les UFs del modul
MP08 Desplegament d'aplicacions web
Totes les UFs del modul
MP09 Disseny d'interfícies web
Totes les UFs del modul
MP10 Formació i Orientació Laboral
Totes les UFs del modul
MP11 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP12 Projecte de síntesi
Totes les UFs del modul
SMX Sistemes Microinformàtics i Xarxes
Tots els mòduls del cicle
MP01 Muntatge i manteniment d’equips
Totes les UFs del modul
MP02 Sistemes Operatius Monolloc
Totes les UFs del modul
MP03 Aplicacions ofimàtiques
Totes les UFs del modul
MP04 Sistemes operatius en xarxa
Totes les UFs del modul
MP05 Xarxes locals
Totes les UFs del modul
MP06 Seguretat informàtica
Totes les UFs del modul
MP07 Serveis de xarxa
Totes les UFs del modul
MP08 Aplicacions Web
Totes les UFs del modul
MP09 Formació i Orientació Laboral
Totes les UFs del modul
MP10 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP11 Anglès
Totes les UFs del modul
MP12 Síntesi
Totes les UFs del modul
CETI Ciberseguretat en Entorns de les Tecnologies de la Informació
Tots els mòduls del cicle
CiberOT Ciberseguretat en Entorns d'Operació
Tots els mòduls del cicle
django_api

APIs amb Django

Les API o Application Programming Interface ens permeten accedir de forma controlada a les dades d'una aplicació web, típicament a través del format JSON, tot i que inicialment es fes servir XML.

Es basen en l'arquitectura software REST. Aquesta estableix estàndards per a HTTP que faciliten la interoperativitat, en particular:

  • Mètodes equivalents al CRUD de BD: GET, POST, PUT, DELETE (però poden definir-se més).
  • HTTP Status code: per definir l'estat de la connexió

Referències teoria i documentació:


APIs simples amb JsonResponse

Abans que res aclarir que per fer crides AJAX no cal tenir instal·lat Django API REST.

Aquestes crides AJAX es poden resoldre amb una simple JsonResponse.

Per exemple, seguint el tutorial de Django «polls», podem implementar una view que ens retorni les dades de les Question en format JSON d'aquesta manera. Per distingir de les views HTML farem un arxiu api.py que sabem que retornarà objectes JSON:

api.py
from django.http import JsonResponse
from polls.models import *
 
#...
 
def get_questions(request):
    jsonData = list( Question.objects.all().values() )
    return JsonResponse({
            "status": "OK",
            "questions": jsonData,
        }, safe=False)

Observa bé què cal per poder serialitzar els objectes del model:

jsonData = list( Question.objects.all().values() )
  1. Tenim un queryset de Questions
  2. Seleccionem només els valors amb .values()
  3. Transformem en una llista amb list( … )

Recorda que abans caldrà que implementis un endpoint, per exemple a /get_questions dins de urls.py:

urls.py
from django.urls import path
 
from . import views, api
 
urlpatterns = [
    path('', views.index, name='index'),
    #...
    path('get_questions', api.get_questions, name='get_questions'),
]

I podrem obtenir les dades des del browser o bé amb una crida per la shell:

$ curl localhost:8000/polls/get_questions
{"questions": [{"id": 1, "question_text": "Qu\u00e8 vols per sopar?", "pub_date": "2022-02-17T09:42:57Z"}, {"id": 2, "question_text": "Qui guanyar\u00e0 la lliga?", "pub_date": "2022-02-17T09:43:13Z"}]}

Si voleu un pretty print del JSON a la línia de comandes podeu fer:

$ curl localhost:8000/polls/get_questions | python3 -m json.tool

I per acabar-ho d'adobar, afegim colors amb pygmentize -l json:

$ curl localhost:8000/polls/get_questions | python3 -m json.tool | pygmentize -l json

El browser sempre és un tiro segur molt còmode:


Protegint els endpoints

Clar que d'aquesta manera el nostre «endpoint» quedarà exposat a qualsevol persona que vulgui accedir a la nostra BD. Si volem fer que només les persones loguejades puguin accedir a les dades de l'aplicació, podem protegir la nostra view molt simplement amb un decorator, en concret el @login_required decorator:

views.py
from django.contrib.auth.decorators import login_required
 
# ...
 
@login_required
def get_questions(request):
    qs = Question.objects.all().values()
    return JsonResponse({
            "status": "OK",
            "questions":list(qs)
        }, safe=False)

Comprova que via shell i la comanda curl ja no puc accedir. En canvi, amb el navegador, si em logo abans sí que podré accedir a les dades.

Decorator @user_passes_test

Existeixen altres decorators que ens faciliten fer un «tunning» més fi de les nostres views. En particular pots mirar el decorator user_passes_test per assegurar-te que l'usuari logat compleix amb certes condicions, com pertànyer a cert grup d'usuaris amb determinats privilegis.


Treballant APIs amb Django REST framework

El mètode de crear views amb JsonResponse vist abans ens permetrà crear APIs accessibles per la pròpia web a través d'AJAX, però no ens facilitarà accedir des d'aplicacions externes com aplicacions mòbils o altres webs.

La Django REST framework ens permetrà obrir les dades a altres aplicacions i dispositius amb seguretat.

Pots seguir el quickstart per agafar una idea ràpida de com utilitzar el REST Framework.

Exercici:

  1. Aplica el quickstart del Django REST Framework al tutorial «polls» oficial de Django.
  2. Crea serializers per als objectes User, Question i Choice.
  3. Realitza requests des de la línia de comandes amb curl per a llistar els diferents tipus objectes (llista complerta i detalls d'un en particular).


Autenticació i autorització

Una part important per a tractar una API és la autenticació (comprovació de identitat) i autorització (quins permisos té aquell usuari identificat).

Django REST Framework authentication reference.

Els dos models d'autenticació més importants són:

  • BasicAuthentication
  • TokenAuthentication


BasicAuthentication

Només recomanada per testing, i no per producció, ja que estem enviant sempre la contrasenya per validar-nos. Per defecte ja ve activada per a la configuració estàndard del REST Framework.

El típic exemple de request seria aquest:

curl -u admin:admin123 http://127.0.0.1:8000/api/users/

De vegades ens pot interessar una alternativa enviant les dades codificades en base64 en els headers:

curl -H 'Authorization:Basic YWRtaW46YWRtaW4xMjM=' http://127.0.0.1:8000/api/users/

Per obtenir el hash en base64 es pot fer:

echo -n "admin:admin123" | openssl base64

O en la versió amb indentació o «pretty print» (això és una implementació particular de Django, en altres no funciona):

curl -H 'Accept: application/json; indent=4' -u admin:admin123 http://127.0.0.1:8000/api/users/

Exercici:

  1. Cerca com ha de ser una query per a enregistrar un nou usuari.
  2. Comprova que si no ens autentiquem no ens deixa enregistrar-lo.
    • Quin status code ens dóna amb l'error d'autenticació? (Utilitza la comanda amb el flag curl -i per visualitzar els headers amb la info).
  3. Comprova què passa si intentem insertar un User amb un username preexistent.
    • Quin status code ens dóna amb l'error?


TokenAuthentication

Aquest és el mètode estàndard per a producció. La idea és que no enviem la contrasenya contínuament, sinó que enviem un token. Per obtenir aquest sí que caldrà emprar la contrasenya, però només un cop mentre que en BasicAuthentication s'envia sempre augmentant les probabilitats de que algú pugui intervenir la contrasenya.

El TokenAuthentication estarà igualment exposat a robatori de sessió o session hijacking, però al menys no comprometem la contrasenya que és una dada sensible. Per tenir un grau mínim de seguretat i no estar exposat a robatoris de sessió és imprescindible emprar sempre HTTPS.

Seguim doc oficial: crear endpooint o URL per obtenir Token.

urls.py
from rest_framework.authtoken import views as apiviews
urlpatterns += [
    path('api-token-auth/', apiviews.obtain_auth_token)
]

Assegura't de tenir a settings.py:

settings.py
INSTALLED_APPS = [
    #...
    'rest_framework',
    'rest_framework.authtoken',
]
 
REST_FRAMEWORK = {
    #...
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ]
}

Per aconseguir el Token:

curl -X POST -d 'username=admin&password=admin123' http://127.0.0.1:8000/api-token-auth/

Per utilitzar el Token:

curl http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'


Objectes aniuats

Exercici amb objectes aniuats:

  1. Crea els serializers per al tutorial oficial Django «polls», per als objectes Question i Choice.
  2. Configura el QuestionSerializer per tal que tingui aniuat («nested») les Choice, de manera que quan demanem una (o vàries) Question ens surti també la info de les seves Choice internes.


URLs personalitzades amb TokenAuthentication del REST framework

Si volem fer les nostres pròpies URLs per a la API i volem afegir-hi algun dels mètdodes d'autenticació del REST framework, ho podem fer així:

from rest_framework.authentication import TokenAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from django.http import JsonResponse
 
@api_view(['GET'])
@authentication_classes([TokenAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticated])
def pin_request(request):
    return JsonResponse({
        "usuari":request.user.username,
        "PIN":3142
        })
 
urlpatterns += [
    path('api/pin_request', pin_request )
]


django_api.txt · Darrera modificació: 2023/04/14 17:06 per enric_mieza_sanchez