Entrar ou criar conta

ULC Lab · implementação reproduzível

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.

APIs REST com FastAPI do zero à integração segura
Ligado ao treinamento APIs REST com FastAPI do zero à integração segura
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.