【发布时间】:2020-10-20 07:57:02
【问题描述】:
总结:
我有一个由几个单独的应用程序构建的完整网络应用程序:
- next.js 面向客户的应用和
- express.js 网络接口。
- 哦,我正在使用 nginx 作为反向代理来为这两者提供服务,不确定这是否会干扰,但似乎它不会干扰我。
除了一件事:gosh darn csurf 实现之外,一切都按预期运行得很好。我无法让它工作并且已经尝试过。所以,我在这里寻求帮助。
关于应用程序:
next.js 应用呈现面向客户的所有内容。它有一个自定义服务器,它只使用头盔和对我的 express.js Web api 的“get-user”请求来填充 req.user 并使用“user”对象响应我的 next.js 应用程序来呈现私人路线。
express.js web api 通过 http 管理用户会话(到目前为止运行良好),仅设置为 next.js 标头的安全 cookie,next.js 客户端包括这些用于对 express.js web api 的请求.
问题:
一切都很好,但是当我尝试在我的 express.js web api 中使用 npm 模块名称“csurf”为我的 next.js 面向客户的应用程序设置一个 csrf cookie 时,我无法让它工作。我已成功设置 csrf 标头并获取该值,然后我使用 redux 在商店中设置它。然后,当我尝试获取 csrftoken 并将其应用于客户端请求时,该请求被拒绝。
下面是简短的代码实现:
- Express.js web api,csurf imp(csurf imp 被注释掉了,因为它不起作用,正在尝试使用 在所有 api 路由上)
import './env';
import express from 'express';
import csrf from 'csurf';
import cors from 'cors';
import morgan from 'morgan';
import cookieParser from 'cookie-parser';
import bodyParser from 'body-parser';
import helmet from 'helmet';
import redis from 'redis';
import connectRedis from 'connect-redis';
import session from 'express-session';
import * as configs from '../config';
import authRouter from './routes/authentication';
import userRouter from './routes/user';
import { setupLocalAuth } from './middleware/auth.middleware';
const RedisStore = connectRedis(session);
const client = redis.createClient({ host: configs.REDIS_CLIENT_HOST });
const port = process.env.PORT || 5000;
const app = express();
app.use(cors({ origin: configs.CORS_ORIGIN, credentials: true }));
if (configs.IS_DEV) {
app.use(morgan('dev'));
}
app.use(helmet());
app.use(cookieParser());
app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(
session({
name: configs.SESSION_NAME,
secret: configs.SESSION_SECRET,
store: new RedisStore({ client }),
saveUninitialized: false,
resave: false,
proxy: configs.IS_DEV ? false : true,
cookie: {
domain: configs.SESSION_COOKIE_DOMAIN,
httpOnly: true,
secure: configs.SESSION_SECURE,
maxAge: 14 * 24 * 60 * 60 * 1000, // 14 days
},
}),
);
/// /////////////////////////////////////////////////////////////////////////////////////////////
//
//
/// /////////////////////////////////////////////////////////////////////////////////////////////
// app.use(csrf({ cookie: true }));
// app.use(function(req, res, next) {
// const token = req.csrfToken();
// res.cookie('XSRF-TOKEN', token);
// // res.locals._csrf = token;
// // res.locals.csrfToken = token;
// next();
// });
if (!configs.IS_DEV) {
app.set('trust proxy', 1);
}
setupLocalAuth(app);
app.use('/api/auth', authRouter);
app.use('/api/user', userRouter);
app.use('/api/facility', facilityRouter);
app.use('/api/team', teamRouter);
app.use('/api/issues', issueRouter);
app.use('/api/forge', forgeRouter);
// error handlers
// development error handler
// will print stacktrace
if (process.env.NODE_ENV !== 'test') {
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: err,
});
});
}
// production error handler
// no stacktraces leaked to user
if (process.env.NODE_ENV === 'production') {
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: {},
});
});
}
app.listen(port, () => {
console.log(`API: Listening on port: ${port}`);
});
然后,在 Next.js 方面:
我所做的只是收集 csrf 令牌并将它们放入我的 redux 存储中以获取 api 请求。不过有一件事:当我从 express.js web api 控制台记录 csrf 令牌以及我在 next.js 端收到的内容时,它们永远不会匹配。所以我认为这是罪魁祸首,但当当对我来说没有意义。我在某个地方犯了一个错误。
还有一个大问题,我什至需要为 SPA 方法执行此操作吗?我在 4 天内设置了一个 Django 应用程序,这非常简单,因为 html 传统上是在服务器上呈现的。
非常感谢!
【问题讨论】:
标签: node.js reactjs security csrf next.js