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
(https://i.imgur.com/YrA6hZX.png)
Donde pone Username es la Password
Y donde pone password es el OTP
Mi API hace esto:
@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
(https://imgur.com/gallery/UwtBKRj)
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:
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.