O erro“O acesso para buscar em ‘…’ da origem ‘…’ foi bloqueado pela política CORS: Nenhum cabeçalho ‘Access-Control-Allow-Origin’ está presente” é um dos erros de desenvolvimento web mais comuns. É aplicado pelo navegador como um mecanismo de segurança. Aqui estão todas as causas e soluções.
📋 Table of Contents
- Por que o CORS existe (compreensão necessária)
- Correção 1: Express.js – Usando o pacote cors
- Correção 2: cabeçalhos CORS manuais no Express
- Correção 3: proxy reverso Nginx
- Correção 4: Frontend – Modo de credenciais
- Noções básicas sobre solicitações de comprovação
- Proxy de desenvolvimento (evite CORS durante o desenvolvimento)
- Erros Comuns
- Perguntas Frequentes
- Conclusão
Por que o CORS existe (compreensão necessária)
CORS (Cross-Origin Resource Sharing) evita que sites maliciosos façam solicitações à API do seu banco usando os cookies logados. Sem o CORS, visitar evil.com poderia fazer chamadas de API silenciosamente para yourbank.com com seus cookies de sessão. O navegador impõe CORS – os servidores declaram quais origens são permitidas.
CORS é um recurso de segurança do navegador — aplica-se apenas a solicitações iniciadas pelo navegador. Curl, Postman e solicitações de servidor para servidor não são afetadas pelo CORS.
Correção 1: Express.js – Usando o pacote cors
npm install cors
const express = require('express');
const cors = require('cors');
const app = express();
// ✅ Allow specific origin (recommended for production)
app.use(cors({
origin: 'https://yourfrontend.com',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true, // required if frontend sends cookies/auth headers
}));
// ✅ Allow multiple origins
const allowedOrigins = ['https://app.example.com', 'https://admin.example.com'];
app.use(cors({
origin: (origin, callback) => {
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error(`Origin ${origin} not allowed by CORS`));
}
},
credentials: true,
}));
// ❌ Allow all origins (never in production with credentials)
app.use(cors({ origin: '*' }));
// Note: wildcard '*' cannot be used with credentials: true
Correção 2: cabeçalhos CORS manuais no Express
// Without the cors package
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://yourfrontend.com');
res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
// Handle preflight requests
if (req.method === 'OPTIONS') {
return res.status(204).end();
}
next();
});
Correção 3: proxy reverso Nginx
location /api/ {
proxy_pass http://localhost:3000/;
# CORS headers
add_header 'Access-Control-Allow-Origin' 'https://yourfrontend.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
# Handle preflight
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://yourfrontend.com';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
Correção 4: Frontend – Modo de credenciais
// ❌ Fetch without credentials — cookies not sent
const res = await fetch('https://api.example.com/user');
// ✅ Include credentials (cookies, authorization headers)
const res = await fetch('https://api.example.com/user', {
credentials: 'include', // send cookies cross-origin
});
// For axios:
axios.defaults.withCredentials = true;
// Or per-request:
axios.get('/api/user', { withCredentials: true });
Importante: Quandocredentials: 'include', o servidor deve definirAccess-Control-Allow-Origin para a origem específica (não*) EAccess-Control-Allow-Credentials: true.
Noções básicas sobre solicitações de comprovação
Para solicitações “não simples” (PUT, DELETE, cabeçalhos personalizados, corpo do aplicativo/json), o navegador envia primeiro uma solicitação de simulação OPTIONS para verificar se a solicitação real é permitida. Se a simulação falhar, a solicitação real nunca será executada.
// Browser sends OPTIONS before POST with JSON body:
OPTIONS /api/users HTTP/1.1
Origin: https://frontend.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
// Server must respond:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://frontend.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400 // cache preflight for 24 hours
Proxy de desenvolvimento (evite CORS durante o desenvolvimento)
// vite.config.ts — proxy /api to backend during dev
export default {
server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
}
}
}
};
// package.json (Create React App) — proxy all /api requests
{
"proxy": "http://localhost:3000"
}
O proxy faz solicitações da mesma origem do frontend (do servidor de desenvolvimento), ignorando totalmente o CORS durante o desenvolvimento — sem comprometer a segurança da produção.
Erros Comuns
// ❌ Mistake 1: CORS headers on wrong route
app.get('/api/data', (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
res.json(data);
});
// OPTIONS preflight hits a different handler that doesn't have CORS headers
// ❌ Mistake 2: Setting headers after response sent
app.use(cors());
app.get('/data', authenticate, (req, res) => {
res.header('Access-Control-Allow-Origin', '*'); // Too late if cors() runs first
});
// ❌ Mistake 3: Multiple conflicting CORS headers
// Browser rejects when two Access-Control-Allow-Origin headers present
// Don't set CORS in both nginx AND Express — pick one place
Perguntas Frequentes
P: Posso desabilitar o CORS no navegador para desenvolvimento?
R: Sim:open -a "Google Chrome" --args --disable-web-security --user-data-dir="/tmp/chrome-dev". SOMENTE para desenvolvedores locais – nunca navegue em sites reais com esta sinalização. Usar um proxy é mais seguro e não requer a desativação da segurança.
P: Por que funciona no Postman, mas não no navegador?
R: O CORS só é aplicado por navegadores. Postman envia a solicitação diretamente sem uma verificação CORS do navegador. Isso confirma que seu servidor está funcionando – você só precisa adicionar cabeçalhos CORS.
P: Devo adicionar cabeçalhos CORS no aplicativo ou no proxy reverso?
R: Apenas um lugar. Se estiver usando o nginx, adicione cabeçalhos no nginx e não os adicione no Express (evita cabeçalhos duplicados). Se estiver implantando em um serviço sem controle nginx, adicione Express.
P: Por que minha API funciona na mesma origem, mas não em origens cruzadas?
R: Isso é exatamente o que o CORS impede: solicitações de origem cruzada exigem permissão explícita do servidor. Solicitações de mesma origem (frontend e API no mesmo domínio/porta) não precisam de cabeçalhos CORS.
P: Posso usar um serviço de proxy CORS?
R: Para prototipagem de desenvolvimento, serviços como cors-anywhere funcionam. Nunca para produção: você envia todas as suas solicitações de API por meio de um serviço de terceiros. Corrija o CORS corretamente em seu servidor.
Conclusão
Corrija o CORS adicionandoAccess-Control-Allow-Origin cabeçalhos em seu servidor – não desativando o CORS ou usando plug-ins de navegador. Para Express.js, ocors O pacote npm lida com todos os casos de forma limpa. Para Nginx, adicione cabeçalhos no nível do proxy. Para desenvolvimento, use a configuração de proxy do Vite para evitar totalmente o CORS. Sempre especifique origens exatas em vez de curinga* na produção, especialmente ao usar credenciais.
🔗 Share this article
✍️ Leave a Comment