Entrar ou criar conta

Laboratório: API REST de Usuários com FastAPI, autenticação JWT e SQLite

Você implementará uma API REST completa para cadastro e autenticação de usuários, protegida por JWT, usando FastAPI e SQLite. Em cerca de 2 horas, será possível criar, autenticar e consultar usuários com validação de segurança básica.

Integração segura de APIs REST com FastAPI
Ligado ao treinamento Integração segura de APIs REST com FastAPI

Roteiro para estudo em ambiente de laboratório ou de teste. Execute apenas em equipamentos, redes e contas que você tenha autorização para usar, com backup e homologação próprios. Comandos podem causar indisponibilidade ou perda de dados. Software e marcas citados pertencem aos seus titulares. Termos de Uso.

ULC-LAB-DESE-0002 · Status de validaçãoNão validado pela Upnetix: roteiro derivado da documentação oficial, para você executar e validar
Duração estimada
120 min
Passos
10
Validações
5
Versões da documentação consultada
FastAPI a versão estável atual · Uvicorn a versão estável atual · SQLAlchemy a versão estável atual · Pydantic a versão estável atual
Objetivo

O objetivo é construir uma API RESTful do zero com FastAPI, incluindo endpoints públicos e protegidos, autenticação JWT, integração com banco de dados SQLite via SQLAlchemy, e documentação automática OpenAPI. Você entenderá o fluxo completo: modelagem de dados, rotas, autenticação e testes básicos.

Topologia

Uma máquina local (192.168.56.10) executa o FastAPI e SQLite. Um cliente HTTP (curl ou httpie) acessa a API via localhost. Não há dependência de rede externa além de downloads de pacotes.


+-------------------+
|   Cliente HTTP    |
| (curl/httpie)     |
+--------+----------+
         |
         | localhost:8000
+--------v----------+
|   FastAPI App     |
|   + SQLite DB     |
+-------------------+

Equipamentos e software

ItemRequisito, licença ou versão
PC ou VM1 vCPU, 1 GB RAM, 1 porta livre (8000), Ubuntu 22.04 ou superior
FastAPIMIT · a versão estável atual
UvicornBSD · a versão estável atual
SQLAlchemyMIT · a versão estável atual
PydanticMIT · a versão estável atual

Roteiro

  1. Preparar ambiente Python isolado

    Evite conflitos de dependências criando um ambiente virtual.

    python3 -m venv venv
    source venv/bin/activate

    O que você deve ver: Prompt do terminal com o prefixo (venv)

  2. Instalar dependências

    Instale FastAPI, Uvicorn, SQLAlchemy e Pydantic. São essenciais para API, servidor, ORM e validação.

    pip install fastapi uvicorn sqlalchemy pydantic

    O que você deve ver: Mensagens de instalação concluída sem erros

  3. Criar o modelo de usuário (SQLAlchemy)

    Defina a estrutura da tabela de usuários para persistência.

    cat > models.py <<EOF
    from sqlalchemy import Column, Integer, String
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    class User(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True, index=True)
        username = Column(String, unique=True, index=True, nullable=False)
        hashed_password = Column(String, nullable=False)
    EOF

    O que você deve ver: Arquivo models.py criado

  4. Configurar o banco SQLite e sessão SQLAlchemy

    Implemente a conexão e a criação automática do banco.

    cat > database.py <<EOF
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    from models import Base
    SQLALCHEMY_DATABASE_URL = 'sqlite:///./test.db'
    engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
    SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    def init_db():
        Base.metadata.create_all(bind=engine)
    EOF

    O que você deve ver: Arquivo database.py criado

  5. Modelos Pydantic para entrada e saída

    Separe o modelo de dados do ORM dos dados expostos na API.

    cat > schemas.py <<EOF
    from pydantic import BaseModel
    class UserCreate(BaseModel):
        username: str
        password: str
    class UserOut(BaseModel):
        id: int
        username: str
        class Config:
            orm_mode = True
    EOF

    O que você deve ver: Arquivo schemas.py criado

  6. Implementar utilitário de hash de senha

    Nunca armazene senhas em texto claro. Use hash seguro.

    cat > security.py <<EOF
    from passlib.context import CryptContext
    pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
    def hash_password(password: str) -> str:
        return pwd_context.hash(password)
    def verify_password(plain_password: str, hashed_password: str) -> bool:
        return pwd_context.verify(plain_password, hashed_password)
    EOF
    pip install passlib[bcrypt]

    O que você deve ver: Arquivo security.py criado e dependência instalada

  7. Implementar geração e validação de JWT

    JWT permite autenticação stateless. Implemente funções para criar e validar tokens.

    cat > jwt_utils.py <<EOF
    from datetime import datetime, timedelta
    from jose import JWTError, jwt
    SECRET_KEY = "supersecretkey"  # Para produção, use variável de ambiente
    ALGORITHM = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES = 30
    def create_access_token(data: dict, expires_delta: timedelta = None):
        to_encode = data.copy()
        expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
        to_encode.update({"exp": expire})
        encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
        return encoded_jwt
    def verify_token(token: str):
        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
            return payload
        except JWTError:
            return None
    EOF
    pip install python-jose

    O que você deve ver: Arquivo jwt_utils.py criado e dependência instalada

  8. Criar o app FastAPI e endpoints

    Implemente rotas para cadastro, login e consulta de perfil protegido.

    cat > main.py <<EOF
    from fastapi import FastAPI, Depends, HTTPException, status
    from sqlalchemy.orm import Session
    from database import SessionLocal, init_db
    from models import User
    from schemas import UserCreate, UserOut
    from security import hash_password, verify_password
    from jwt_utils import create_access_token, verify_token
    from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
    init_db()
    app = FastAPI()
    oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/login")
    def get_db():
        db = SessionLocal()
        try:
            yield db
        finally:
            db.close()
    @app.post("/register", response_model=UserOut)
    def register(user: UserCreate, db: Session = Depends(get_db)):
        db_user = db.query(User).filter(User.username == user.username).first()
        if db_user:
            raise HTTPException(status_code=400, detail="Usuário já existe")
        hashed = hash_password(user.password)
        new_user = User(username=user.username, hashed_password=hashed)
        db.add(new_user)
        db.commit()
        db.refresh(new_user)
        return new_user
    @app.post("/login")
    def login(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
        user = db.query(User).filter(User.username == form_data.username).first()
        if not user or not verify_password(form_data.password, user.hashed_password):
            raise HTTPException(status_code=401, detail="Credenciais inválidas")
        token = create_access_token({"sub": user.username})
        return {"access_token": token, "token_type": "bearer"}
    @app.get("/me", response_model=UserOut)
    def read_users_me(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
        payload = verify_token(token)
        if not payload:
            raise HTTPException(status_code=401, detail="Token inválido")
        username = payload.get("sub")
        user = db.query(User).filter(User.username == username).first()
        if user is None:
            raise HTTPException(status_code=404, detail="Usuário não encontrado")
        return user
    EOF

    O que você deve ver: Arquivo main.py criado

  9. Iniciar o servidor FastAPI

    Coloque a API no ar para testes.

    uvicorn main:app --reload

    O que você deve ver: Mensagem 'Uvicorn running on http://127.0.0.1:8000'

  10. Testar documentação automática OpenAPI

    Acesse a interface Swagger para explorar e testar a API.

    Acesse http://127.0.0.1:8000/docs no navegador

    O que você deve ver: Interface Swagger interativa com endpoints /register, /login, /me

Como saber que funcionou

TesteComandoCritério
Registrar novo usuáriocurl -X POST http://127.0.0.1:8000/register -H 'Content-Type: application/json' -d '{"username": "alice", "password": "senha123"}'Retorno JSON com id e username
Login e obtenção de token JWTcurl -X POST http://127.0.0.1:8000/login -d 'username=alice&password=senha123' -H 'Content-Type: application/x-www-form-urlencoded'Retorno JSON com access_token
Acessar endpoint protegido com tokencurl -H 'Authorization: Bearer <access_token>' http://127.0.0.1:8000/meRetorno JSON com id e username
Tentar acessar /me sem tokencurl http://127.0.0.1:8000/meRetorno HTTP 401
Registrar usuário já existentecurl -X POST http://127.0.0.1:8000/register -H 'Content-Type: application/json' -d '{"username": "alice", "password": "outra"}'Retorno HTTP 400

Troubleshooting

SintomaCausa provávelCorreção
Erro 'no such table: users'Banco SQLite não inicializadoVerifique se init_db() foi chamado antes de iniciar o app
Erro 'ModuleNotFoundError' ao importar módulosDependências não instaladas ou ambiente virtual não ativadoAtive o venv e rode pip install novamente
Token JWT inválido ou expiradoToken malformado ou tempo de expiração atingidoFaça login novamente para obter novo token
Senha não é aceita mesmo corretaProblema no hash ou dependência do passlib/bcryptConfirme instalação do passlib[bcrypt] e reinicie o app

Segurança e hardening

  • Nunca use SECRET_KEY hardcoded em produção; utilize variável de ambiente
  • Tokens JWT devem ter expiração curta
  • Senhas sempre com hash forte (bcrypt)
  • Limite tentativas de login para evitar brute force
  • Não exponha stack trace detalhado em produção

Checklist final

Referências

  1. FastAPI - Tutorial · FastAPI (fastapi.tiangolo.com)
  2. Pydantic - Documentação · Pydantic-docs.helpmanual (pydantic-docs.helpmanual.io)
  3. SQLAlchemy - ORM Tutorial · Docs.sqlalchemy (docs.sqlalchemy.org)
Verificação editorial
Publicado
09/09/2026
Última revisão
09/09/2026
Versão do conteúdo
1.0
Referências
3 oficiais
Revisão técnica
redação e revisão por IA, URLs conferidas na publicação
Status
Atual
Encontrou um erro? Escreva para comercial@upnetix.com.br com o endereço da página. A revisão semestral por IA nunca altera comandos ou configurações sem passar pela fila de revisão.