Como obtengo los datos de la autorizacion (Basic Auth) en un request API | Python Django

Iniciado por Drakaris, 18 Septiembre 2021, 21:33 PM

0 Miembros y 1 Visitante están viendo este tema.

Drakaris

Buenos dias, ¿como estais?  :D

Tengo un pequeño problemilla. Os cuento, estoy haciendo una API en Django [sin Django REST Framework  :silbar:] y esta API el usuario puede utilizarla si se autentifica con metodo Basic Auth

Donde pone Username es la Password
Y donde pone password es el OTP

Mi API hace esto:
Código (python) [Seleccionar]

@csrf_exempt
   def requests(self,req,table:str,columns:list=False):
       try:
           try:
               if not loginAdmin(req.headers['password'], int(req.headers['otp'])):
                   raise Exception("Access denied")
           except:
               raise Exception("You need authentication")
           conn = sqlite3.connect(Environment().pathDB())
           cursor = conn.cursor()

es parte del codigo, pues yo estoy aqui seleccionando las keys password y otp del header, pero segun me he informado de que se muestra en el header en la key "Authorization" con encriptacion BASE64
https://learning.postman.com/docs/sending-requests/authorization/#basic-auth

Pero yo he hecho return de req.headers y no hay ninguna key llamada "Authorization" o "Authorization", pero en el postman si se ve

He estado buscando info y segun dicen si con req.META hay una HTTP_AUTHORIZATION, pero no se muestra ninguno
Citar
GATEWAY_INTERFACESERVER_PROTOCOLREQUEST_METHODQUERY_STRINGREQUEST_URISCRIPT_NAMEPATH_INFOPATH_TRANSLATEDHTTP_HOSTHTTP_USER_AGENTHTTP_ACCEPT_ENCODINGHTTP_ACCEPTHTTP_CONNECTIONSERVER_SIGNATURESERVER_SOFTWARESERVER_NAMESERVER_ADDRSERVER_PORTREMOTE_ADDRDOCUMENT_ROOTREQUEST_SCHEMECONTEXT_PREFIXCONTEXT_DOCUMENT_ROOTSERVER_ADMINSCRIPT_FILENAMEREMOTE_PORTmod_wsgi.script_namemod_wsgi.path_infomod_wsgi.process_groupmod_wsgi.application_groupmod_wsgi.callable_objectmod_wsgi.request_handlermod_wsgi.handler_scriptmod_wsgi.script_reloadingmod_wsgi.listener_hostmod_wsgi.listener_portmod_wsgi.enable_sendfilemod_wsgi.ignore_activitymod_wsgi.request_startmod_wsgi.request_idmod_wsgi.script_startwsgi.versionwsgi.multithreadwsgi.multiprocesswsgi.run_oncewsgi.url_schemewsgi.errorswsgi.inputwsgi.input_terminatedwsgi.file_wrapperapache.versionmod_wsgi.versionmod_wsgi.total_requestsmod_wsgi.thread_idmod_wsgi.thread_requests

Aqui dejo la API:
Código (python) [Seleccionar]

from sources import loginAdmin,Environment,logFile
import sqlite3,re
from django.urls import  path
from django.http import JsonResponse, HttpResponse, QueryDict
from django.views.decorators.csrf import csrf_exempt

"""
==========================API REST==========================
SYNTAX:
   127.0.0.1/api[/table,table1,table3,...][/column]?<key>=[>|<|>=|<=]<value>&[|]<key>=[>|<|>=|<=]<value>&LIMIT=<min>[,max]
============================================================
IMPORTANT:
   For do a request you need authentication with password and OTP

EXAMPLES:
   GET:
       127.0.0.1/api/server -> SELECT * FROM server
       127.0.0.1/api/server?LIMIT=5 -> SELECT * FROM server LIMIT 5
       127.0.0.1/api/server?password=ejem&id=1&LIMIT=5,7 -> SELECT * FROM server WHERE password='ejem' AND id=1 LIMIT 5,7
       127.0.0.1/api/server/otp,id -> SELECT otp,id FROM server
       127.0.0.1/api/server/otp?id=1&password=hola -> SELECT otp FROM server WHERE id=1 AND password='hola'
       127.0.0.1/api/server/otp?id=1&|password=hola -> SELECT otp FROM server WHERE id=1 OR password='hola'
       
   POST:
       127.0.0.1/api/server -> INSERT INTO server (otp,ejem) VALUES (1234,'1233da')
           Body x-www-form-urlencoded
               key     value
               --------------------
               otp     1234
               ejem    1233da
               
       IMPORTANT: The params in the url doesn't affect
       
   PUT:
       127.0.0.1/api/server?port=8899&|password=h -> UPDATE server SET otp='1234', ejem='1233da' WHERE port=8899 OR password='h'
           Body x-www-form-urlencoded
               key     value
               --------------------
               otp     1234
               ejem    1233da
               
   DELETE:
       127.0.0.1/api/server?port=8899&password=h -> DELETE FROM server WHERE port=8899 AND password='h'
           not body data
"""

class getData:
   def __init__(self,data):
       self.list = QueryDict(data)
       self.output = ''

   # This method returns key1,key2,key3...
   # For clause as SELECT, INSERT
   def getKeys(self):
       for t in self.list:
           self.output+=f'{t},'
       self.output = re.sub(r",$","",self.output)
       return self.output

   # This method returns value1,value2,value3...
   # For clause as SELECT, INSERT
   def getValues(self):
       for t in self.list:
           try:
               if int(self.list[t]):
                   self.output+=f'{self.list[t]},'
           except:
               self.output += f"'{self.list[t]}',"
       self.output = re.sub(r",$","",self.output)
       return self.output

   # This method returns key1=value1, key2=value2, key3=value3
   # being '=' the 'delimitator'
   # For clause as UPDATE
   def keysValues(self,delimitator):
       for value in self.list:
           self.output+=f"{value}{delimitator}'{self.list[value]}', "
       self.output = re.sub(r", $", "", self.output)
       return self.output

class Database:
   # if there are columns, show it
   def columns(self,columns):
       if columns:
           return  columns
       else:
           return "*"

   # This method add the operator specified in the url
   def keyWhere(self,key):
       operator = re.sub(r"[^>|<|=]","",key)
       value = re.sub(r"[>|<|=]","",key)
       if operator == "":
           operator="="
       try:
           if int(value):
               return f"{operator}{value}"
       except:
           return f"{operator}'{value}'"

   def LimitClause(self,params):
       if params:
           output = ''
           for key in params:
               if key=="LIMIT":
                   output=f" LIMIT {params[key]}"
           return output
       else:
           return ""

   # This method add AND or OR in each condition in WHERE
   def WhereClause(self,params):
       if params:
           output=''
           for key in params:
               if key=="LIMIT":
                   continue
               operator = "OR" if key[0]=="|" else "AND"
               if list(params).index(key) > 0:
                   output+=f" {operator} {key[1::] if operator=='OR' else key}{self.keyWhere(params[key])}"
               else:
                   output += f"WHERE {key[1::] if operator=='OR' else key}{self.keyWhere(params[key])}"
           return output
       else:
           return ""

   @csrf_exempt
   def requests(self,req,table:str,columns:list=False):
       try:
           try:
               if not loginAdmin(req.headers['password'], int(req.headers['otp'])):
                   raise Exception("Access denied")
           except:
               raise Exception("You need authentication")
           conn = sqlite3.connect(Environment().pathDB())
           cursor = conn.cursor()
           if req.method == "GET":
               data = cursor.execute(f"SELECT {self.columns(columns)} FROM {table} {self.WhereClause(req.GET.dict())}{self.LimitClause(req.GET.dict())}")
               data = list(data)
               conn.close()
               if len(data) == 0:
                   data = None
               return JsonResponse({
                   "result": data
               })
           elif req.method == "POST":
               if columns:
                   raise Exception("POST not allowed")
               cursor.execute(f"INSERT INTO {table} ({getData(req.body).getKeys()}) VALUES ({getData(req.body).getValues()})")
               conn.commit()
               conn.close()
               return JsonResponse({"INSERT":True})
           elif req.method == "PUT":
               if columns:
                   raise Exception("PUT not allowed")
               cursor.execute(f"UPDATE {table} SET {getData(req.body).keysValues('=')} {self.WhereClause(req.GET.dict())}")
               conn.commit()
               conn.close()
               return JsonResponse({"UPDATE": True})
           elif req.method == 'DELETE':
               if columns:
                   raise Exception("DELETE not allowed")
               cursor.execute(f"DELETE FROM {table} {self.WhereClause(req.GET.dict())}")
               conn.commit()
               conn.close()
               return JsonResponse({"DELETE": True})
       except sqlite3.Error as err:
           return HttpResponse(logFile(True).message(f"DB -> {err}",True))
       except Exception as err:
           return HttpResponse({f"Error in the API REST -> {err}"})
urlpatterns=[
   path('<table>',Database().requests),
   path('<table>/<columns>',Database().requests)
]


¿Como yo puedo mostrar los datos del Auth? Muchas gracias.

P.D: Cualquier comentario, sugerencia u opinion sobre la mejora del código, lo agradecería mucho. Mil gracias.
Lo increible, no es lo que ves, sino como es