with example creating apis python api flask api-key

python - example - ¿Hay una forma aceptada de usar las claves API para la autenticación en Flask?



python flask api example (3)

Tengo una pequeña API a la que me gustaría agregar autenticación. Me gustaría poder generar claves de API para los consumidores de API; Los consumidores pueden utilizar incluir las claves con sus solicitudes de solicitud.

¿Hay una biblioteca de matraz que hace algo como esto? ¿O hay una forma típica de hacerlo? Hice una búsqueda y solo me topé con this , lo que realmente no profundiza mucho. Estoy buscando una biblioteca si la hay.


Aquí hay una función que usa hashlib que me ha funcionado bastante bien:

def generate_hash_key(): """ @return: A hashkey for use to authenticate agains the API. """ return base64.b64encode(hashlib.sha256(str(random.getrandbits(256))).digest(), random.choice([''rA'', ''aZ'', ''gQ'', ''hH'', ''hG'', ''aR'', ''DD''])).rstrip(''=='')

Una posible solución para implementar esto en la aplicación podría ser aplicar un decorador en cada ruta que desee proteger.

Ejemplo:

def get_apiauth_object_by_key(key): """ Query the datastorage for an API key. @param ip: ip address @return: apiauth sqlachemy object. """ return model.APIAuth.query.filter_by(key=key).first() def match_api_keys(key, ip): """ Match API keys and discard ip @param key: API key from request @param ip: remote host IP to match the key. @return: boolean """ if key is None or ip is None: return False api_key = get_apiauth_object_by_key(key) if api_key is None: return False elif api_key.ip == "0.0.0.0": # 0.0.0.0 means all IPs. return True elif api_key.key == key and api_key.ip == ip: return True return False def require_app_key(f): """ @param f: flask function @return: decorator, return the wrapped function or abort json object. """ @wraps(f) def decorated(*args, **kwargs): if match_api_keys(request.args.get(''key''), request.remote_addr): return f(*args, **kwargs) else: with log_to_file: log.warning("Unauthorized address trying to use API: " + request.remote_addr) abort(401) return decorated

Y luego puedes usar el decorador como tal:

@require_app_key def delete_cake(version, cake_id): """ Controller for API Function that gets a cake by ID @param cake_id: cake id @return: Response and HTTP code """

Este ejemplo utiliza SQLAlchemy para almacenar claves en la base de datos (podría usar SQLite).

Puede ver la implementación aquí: https://github.com/haukurk/flask-restapi-recipe .


La forma "típica" de generar una clave API es crear un UUID (generalmente creando un hash md5 de algún subconjunto de información del usuario + información algo aleatoria (como la hora actual)).

Todas las claves API, sin embargo, deben ser UUIDs. El hash hexadecimal creado por md5 cumple con este requisito, pero ciertamente existen otros métodos.

Una vez que haya creado una clave para el usuario, guárdela en la base de datos como parte de la información del usuario y verifique que su clave (almacenada en una cookie, por lo general) coincida con la que tiene. La mecánica real de esto se describe (en cierto modo) en la página a la que se vinculó.


Para las claves de autenticación, cree un valor aleatorio y almacene ese valor en una base de datos. random() proporciona una entropía insuficiente para cosas como esta, así que usa os.urandom() .

El enlace al que has publicado tiene un buen ejemplo de cómo manejar las cosas con una función de decoración. En la función de decoración, verifique que el valor de la clave de aplicación esté establecido en la solicitud, verifique que sea válido en la base de datos y luego devuelva la función. Si la clave de aplicación no es válida, raise AuthenticationError("Invalid appkey") y listo.

El ejemplo al que has vinculado es un poco confuso. Me gusta la demostración de ¿Cómo hacer una cadena de decoradores funcionales? mejor.

def checkAppKey(fn): def inner(*args, **kwargs): #appkey should be in kwargs try: AppKey.get(appkey) except KeyError: raise AuthenticationError("Invalid appkey") #Whatever other errors can raise up such as db inaccessible #We were able to access that API key, so pass onward. #If you know nothing else will use the appkey after this, you can unset it. return fn(*args, **kwargs) return inner