Os JSON Web Tokens são fáceis de usar e depurar, mas também oferecem um aumento de segurança impressionante.

A autenticação quebrada continua a ser uma vulnerabilidade persistente em aplicativos da Web modernos - ela ainda está classificada entre os 10 principais riscos de segurança de API do OWASP.

Os efeitos dessa vulnerabilidade podem ser graves. Eles podem conceder acesso não autorizado a dados confidenciais e comprometer a integridade do sistema. Para garantir de forma eficaz o acesso seguro aos aplicativos e seus recursos, é vital que você use mecanismos de autenticação robustos.

Descubra como você pode implementar a autenticação do usuário no Flask usando JSON Web Tokens (JWT), um método baseado em token popular e eficaz.

Autenticação baseada em token usando tokens Web JSON

A autenticação baseada em token usa uma sequência criptografada de caracteres para validar e autorizar o acesso a um sistema ou recurso. Você pode implementar esse tipo de autenticação usando vários métodos, incluindo tokens de sessão, chaves de API e JSON Web Tokens.

instagram viewer

Os JWTs, em particular, oferecem uma abordagem segura e compacta para transmitir as credenciais de usuários necessárias entre aplicativos e servidores do lado do cliente.

Um JWT consiste em três componentes principais: o cabeçalho, a carga útil e a assinatura. O cabeçalho contém metadados sobre o token, incluindo o algoritmo de hash usado para codificar o token.

A carga útil contém as credenciais reais do usuário, como ID do usuário e permissões. Por fim, a assinatura garante a validade do token verificando seu conteúdo por meio de uma chave secreta.

Usando JWTs, você pode autenticar usuários e armazenar dados de sessão dentro do próprio token.

Configurar um projeto Flask e um banco de dados MongoDB

Para começar, crie um novo diretório de projeto usando um terminal:

projeto de balão mkdir
cd flask-project

Em seguida, instale virtualenv, para criar um ambiente de desenvolvimento virtual local para seu projeto Flask.

virtualenv venv

Por fim, ative o ambiente virtual.

# Unix ou MacOS: 
fonte venv/bin/ativar

# Janelas:
.\venv\Scripts\ativar

Você pode encontrar o código deste projeto neste Repositório GitHub.

Instale os pacotes necessários

No diretório raiz da pasta do seu projeto, crie um novo requisitos.txt arquivo e adicione estas dependências para o projeto:

frasco
pyjwt
python-dotenv
pimongo
bcrypt

Por fim, execute o comando abaixo para instalar os pacotes. Assegure-se de ter pip (gerenciador de pacotes) instalado; se não, instale-o em seu sistema Windows, Mac ou Linux.

pip install -r requisitos.txt

Criar um banco de dados MongoDB

Vá em frente e crie um banco de dados MongoDB. Você pode configurar um banco de dados MongoDB local, alternativamente, criar um cluster no MongoDB Atlas, um serviço MongoDB baseado em nuvem.

Depois de criar o banco de dados, copie o URI de conexão, crie um .env arquivo no diretório raiz do seu projeto e adicione-o da seguinte maneira:

MONGO_URI=""

Por fim, configure a conexão com o banco de dados de seu aplicativo Flask. Crie um novo utils/db.py arquivo no diretório raiz do seu projeto, com este código:

de pimongo importar MongoClientName

defconnect_to_mongodb(mongo_uri):
cliente = MongoClient (mongo_uri)
banco de dados = cliente.get_database("Usuários")
retornar banco de dados

Esta função estabelece uma conexão com o banco de dados MongoDB usando o URI de conexão fornecido. Em seguida, cria um novo Usuários coleção se não existir e retorna a instância de banco de dados correspondente.

Criar o Servidor Web Flask

Com o banco de dados configurado, vá em frente e crie um app.py arquivo no diretório raiz da pasta do projeto e adicione o código a seguir para criar uma instância do aplicativo Flask.

de frasco importar Frasco
de rotas.user_auth importar register_routes
de utils.db importar connect_to_mongodb
importar os
de dotenv importar load_dotenv

app = Frasco (__name__)
load_dotenv()

mongo_uri = os.getenv('MONGO_URI')
db = connect_to_mongodb (mongo_uri)

register_routes (aplicativo, banco de dados)

se __nome__ == '__principal__':
app.run (depurar=Verdadeiro)

Crie os endpoints da API de autenticação

Para implementar a autenticação do usuário em seu aplicativo Flask, é crucial definir os endpoints de API necessários que lidam com operações relacionadas à autenticação.

No entanto, primeiro defina o modelo para os dados dos usuários. Para isso, crie um novo model/user_model.py arquivo no diretório raiz e adicione o código a seguir.

de pymongo.coleção importar Coleção
de bson.objectid importar ObjectId

aulaDo utilizador:
def__iniciar__(auto, coleção: Coleção, nome de usuário: str, senha: str):
self.coleção = coleção
self.username = nome de usuário
self.password = senha
defsalvar(auto):
usuário_dados = {
'nome de usuário': self.username,
'senha': self.senha
}
resultado = self.collection.insert_one (user_data)
retornar str (resultado.inserted_id)

@staticmethod
defencontrar_por_id(coleção: Coleção, user_id: str):
retornar coleção.find_one({'_eu ia': ObjectId (user_id)})

@staticmethod
deffind_by_username(coleção: Coleção, nome de usuário: str):
retornar coleção.find_one({'nome de usuário': nome de usuário})

O código acima especifica um Do utilizador classe que serve como um modelo de dados e define vários métodos para interagir com uma coleção do MongoDB para executar operações relacionadas ao usuário.

  1. O salvar O método salva um novo documento do usuário com o nome de usuário e a senha fornecidos para a coleção do MongoDB e retorna o ID do documento inserido.
  2. O encontrar_por_id e find_by_username Os métodos recuperam documentos do usuário da coleção com base no ID do usuário ou nome de usuário fornecido, respectivamente.

Definir as Rotas de Autenticação

  1. Vamos começar definindo a rota de registro. Essa rota adicionará novos dados do usuário à coleção de usuários do MongoDB. No diretório raiz, crie um novo rotas/user_auth.py arquivo e o seguinte código.
    importar jwt
    de ferramentas de funções importar envolve
    de frasco importar jsonify, pedido, make_response
    de models.user_model importar Do utilizador
    importar bcrypt
    importar os

    defregister_routes(aplicativo, banco de dados):
    coleção = db.users
    app.config['CHAVE SECRETA'] = os.urandom(24)

    @app.route('/api/register', method=['POST'])
    defregistro():

    nome de usuário = request.json.get('nome de usuário')
    senha = request.json.get('senha')

    existing_user = User.find_by_username (coleção, nome de usuário)
    se Usuário existente:
    retornar jsonify({'mensagem': 'Nome de usuário já existe!'})

    hashed_password = bcrypt.hashpw (password.encode('utf-8'), bcrypt.gensalt())
    new_user = Usuário (coleção, nome de usuário, hasshed_password.decode('utf-8'))
    user_id = new_user.save()

    retornar jsonify({'mensagem': 'Usuário cadastrado com sucesso!', 'ID do usuário': ID do usuário})

  2. Implemente a funcionalidade de login para lidar com o processo de autenticação e verificar as credenciais do usuário. Na rota de registro, adicione o seguinte código.
     @app.route('/api/login', method=['POST'])
    defConecte-se():
    nome de usuário = request.json.get('nome de usuário')
    senha = request.json.get('senha')
    user = User.find_by_username (coleção, nome de usuário)
    se do utilizador:
    se bcrypt.checkpw (senha.encode('utf-8'), do utilizador['senha'].codificar('utf-8')):
    token = jwt.encode({'ID do usuário': str (usuário['_eu ia'])}, app.config['CHAVE SECRETA'], algoritmo='HS256')

    resposta = make_response (jsonify({'mensagem': 'Login com sucesso!'}))
    resposta.set_cookie('símbolo', símbolo)
    retornar resposta

    retornar jsonify({'mensagem': 'Nome de usuário ou senha inválidos'})

    O endpoint de login faz duas coisas: verifica as credenciais de usuário fornecidas e, após a autenticação bem-sucedida, gera um JWT exclusivo para esse usuário. Ele define esse token como um cookie na resposta, junto com uma carga JSON indicando um login bem-sucedido. Se as credenciais forem inválidas, ele retornará uma resposta JSON para indicar isso.
  3. Defina uma função de decorador que verifique os JSON Web Tokens (JWTs) transmitidos junto com as solicitações de API subsequentes. Adicione o código abaixo dentro do register_routes bloco de código de função.
    deftoken_required(f):
    @wraps (f)
    defdecorado(*args, **kwargs):
    token = request.cookies.get('símbolo')

    senão símbolo:
    retornar jsonify({'mensagem': 'Símbolo está faltando!'}), 401

    tentar:
    data = jwt.decode (token, app.config['CHAVE SECRETA'], algoritmos=['HS256'])
    current_user = User.find_by_id (coleção, dados['ID do usuário'])
    exceto jwt. ExpiredSignatureError:
    retornar jsonify({'mensagem': 'Token expirou!'}), 401
    exceto jwt. InvalidTokenError:
    retornar jsonify({'mensagem': 'Token inválido!'}), 401

    retornar f (current_user, *args, **kwargs)

    retornar decorado

    Essa função de decorador garante a presença de um token JWT válido em solicitações de API subsequentes. Ele verifica se o token está ausente, expirado ou válido e retorna uma resposta JSON apropriada, se estiver.
  4. Finalmente, crie uma rota protegida.
     @app.route('/api/users', method=['GET'])
    @token_required
    defget_users(usuário atual):
    usuários = lista (coleção.find({}, {'_eu ia': 0}))
    retornar jsonify (usuários)

Esse terminal manipula a lógica para recuperar dados do usuário do banco de dados, mas exige que o cliente que envia solicitações inclua um token válido para acessar os dados.

Por fim, execute o comando abaixo para ativar o servidor de desenvolvimento.

corrida de balão

Para testar o registro, o login e o endpoint dos usuários protegidos, você pode usar o Postman ou qualquer outro cliente API. Enviar pedidos para http://localhost: 5000/api/e observe as respostas para verificar a funcionalidade desses endpoints da API.

A autenticação de token é uma medida de segurança infalível?

Os JSON Web Tokens fornecem uma maneira robusta e eficaz de autenticar usuários para seu aplicativo da web. No entanto, é importante entender que a autenticação de token não é infalível; é apenas uma peça de um quebra-cabeça de segurança maior.

Combine autenticação de token com outras práticas recomendadas de segurança. Lembre-se de monitorar continuamente e adotar práticas de segurança consistentes; você aumentará significativamente a segurança geral de seus aplicativos Flask.