我有一个 React 前端调用 NextJS 端点。我相信使用
next.config.js
文件在服务器上设置了正确的标头...
module.exports = {
reactStrictMode: true,
webpack: (config, options) => {
if (!options.isServer) {
config.resolve.fallback.fs = false
}
return config
},
async headers() {
return [
{
source: '/api/:path*',
headers: [
{ key: 'origins', value: '*' },
{ key: 'Bypass-Tunnel-Reminder', value: '*' },
{ key: 'Access-Control-Allow-Origin', value: '*' },
{ key: 'Access-Control-Request-Methods', value: 'POST, GET, OPTIONS' },
{ key: 'Access-Control-Allow-Headers', value: 'Authorization, Content-Type' },
],
},
]
},
}
尽管如此,当我从前端调用端点时,我不断收到 CORS 错误。
这是前端代码...
axios.post(
'http://localhost:3001/github/setCredentials',
{
accessCode,
},
{
headers: {
Authorization: localStorage.getItem('jwt_token'),
'Content-Type': 'application/x-www-form-urlencoded',
},
},
)
jwt_token
看起来像“承载者端点看起来像这样...
const authenticate = (method, req, res) =>
new Promise((resolve, reject) => {
passport.authenticate(method, { session: false }, (error, token) => {
if (error) {
reject(error)
} else {
resolve(token)
}
})(req, res)
})
passport.use(jwtStrategy)
const handler = nextConnect({
onError: (err, req: NextApiRequest, res: NextApiResponse, next) => {
console.error(err.stack)
res.status(500).end('Something broke!')
},
onNoMatch: (req: NextApiRequest, res: NextApiResponse) => {
res.status(404).end('Page is not found')
},
})
.use(passport.initialize())
.post(async (req: NextApiRequest, res: NextApiResponse) => {
try {
const user = await authenticate('jwt', req, res)
if (!user) return res.status(403).json({ error: 'Unauthenticated user' })
return res.status(200).json({ success: true })
} catch (err) {
return res.status(500).json({ error: err.toString() })
}
})
export default handler
passport.js 身份验证策略如下所示...
const opts: any = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken()
opts.secretOrKey = JWT_SECRET
export const jwtStrategy = new JwtStrategy(opts, function (jwt_payload, done) {
mongoose
.getUserByEthAddress(jwt_payload.address)
.then((user: User | null) => {
return done(null, user)
})
.catch((err) => {
return done(err, false)
})
})
有趣的是(令人沮丧?),击中我的其他端点不会导致 CORS 错误。另外,当我从请求中删除“Authorization”标头时,我收到中间件抛出的典型 403 错误,无法找到用户,但没有 CORS 错误。
此外,当我使用授权令牌和所有内容在 Postman 上进行此调用时,它运行良好,因此身份验证层不是问题。
有什么想法可能导致这种情况吗?我读到的所有内容似乎都在
next.config.js
文件中设置“Access-Control...”标头可以解决此问题,但事实并非如此。谢谢!
@jub0bs 引导我解决了这个问题。我需要做几件事。
.use(async (req: NextApiRequest, res: NextApiResponse, next) => {
await NextCors(req, res, {
// Options
methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],
origin: '*',
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
})
next()
})
.options((req: NextApiRequest, res: NextApiResponse) => {
return res.status(200).send('ok')
})
然后,我的护照中间件使用一个
req.user
对象填充请求,我可以在处理 POST 方法时使用该对象。
我将 next.js 中间件配置为处理接受的来源,并仅在生产模式接受来源类型时返回网站或路由。对于本地开发,我将原始值设置为
*
,因为不需要为本地主机处理 CORS。您可以将此代码复制粘贴到您的 middleware.ts
文件中。
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
const isProduction = process.env.DATASET === 'production';
const corsOrigins = isProduction
? [
'domain1',
'domain2',
'domain3',
'domain4',
]
: ['*'];
export function middleware(req: NextRequest) {
const origin = req.headers.get('origin');
const res = NextResponse.next();
// Set CORS headers
res.headers.set('Access-Control-Allow-Credentials', 'true');
res.headers.set('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT');
res.headers.set(
'Access-Control-Allow-Headers',
'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
);
if (corsOrigins.includes('*') || corsOrigins.includes(origin || '')) {
res.headers.set('Access-Control-Allow-Origin', origin || '*');
}
return res;
}
export const config = {
matcher: '/api/:path*', // Match all API routes
};
请修改
corsOrigins
数组值(添加所有您需要的域)。