use*_*061 6 javascript nginx node.js express express-session
我正在将前端与后端存储库分离。为此,我将服务器托管在家庭网络上的个人 Raspberry Pi 3 上。我的前端由 Netlify 托管。我遇到了一个问题,尽管我可以在 Postman 中看到 cookie 设置,但我无法使用 Express.Js 在客户端上设置 cookie。
我当前的设置如下:
FE (Netlify - example.com) -> Nginx (Reverse Proxy - api.example.com) -> Node.js (Express - listening for http)
Run Code Online (Sandbox Code Playgroud)
我无法登录使用 Express-Session 进行会话的应用程序。我可以发布登录信息,但没有看到响应中设置了 cookie。话虽如此,我在 Heroku 上工作了(FE + BE 在同一个仓库上)
我尝试了很多方法来使其正常工作,但都失败了。
我尝试过的一些解决方案是:
.example.com{ withCredentials: true }proxy_set_header X-Forwarded-Proto https;server {
root /var/www/example-backend;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
Run Code Online (Sandbox Code Playgroud)
const express = require('express');
const bodyParser = require('body-parser');
const logger = require('morgan');
const passport = require('passport');
const session = require('express-session');
const cors = require('cors');
const app = express();
const routes = require('./routes');
const server = require('./db');
app.use(logger('dev'));
app.use(cors({
origin: 'https://example-frontend.netlify.com',
credentials: true,
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.set('trust proxy', 1)
app.use(
session({
secret: 'secrets',
resave: false,
saveUninitialized: true,
cookie: { domain: '.example-frontend.netlify.com' }
})
);
app.use(passport.initialize());
app.use(passport.session());
const Account = require('./models/account');
passport.use(Account.createStrategy());
passport.serializeUser(Account.serializeUser());
passport.deserializeUser(Account.deserializeUser());
app.use('/api', routes);
app.listen(3000, async () => {
await server.start();
console.log('HTTP running on port 3000');
});
Run Code Online (Sandbox Code Playgroud)
const express = require('express');
const router = express.Router();
router.get('/testCookie', (req, res) => {
res.cookie('test', 'hi', { domain: 'example-frontend.netlify.com'})
res.sendStatus(200);
});
Run Code Online (Sandbox Code Playgroud)
import axios from 'axios';
const API_ROOT =
process.env.NODE_ENV === 'production'
? 'https://api.example.com/api'
: '/api';
const API_RECIPE = `${API_ROOT}/recipe`;
const API_ACCOUNT = `${API_ROOT}/account`;
export const testCookie = () =>
axios.get(`${API_ROOT}/testCookie`, { withCredentials: true });
Run Code Online (Sandbox Code Playgroud)
我认为这与跨域 cookie 有关,但我已经耗尽资源来了解可能出现的问题。我觉得这可能是在 nginx 级别,因为这是当前设置和 Heroku 设置之间唯一发生变化的部分。
任何帮助将不胜感激!
更新:我不确定哪个部分解决了这个问题,但这是我的工作代码
后端
app.use(
require('express-session')({
secret: process.env.MONGO_SESSIONS_SECRET,
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 7,
...(process.env.NODE_ENV !== 'dev'
? { domain: '.example.com' }
: {}),
},
store: store,
resave: true,
saveUninitialized: true,
})
);
app.use((req, res, next) => {
const acceptedOrigins = [
'http://example.com',
'http://beta.example.com',
'http://localhost:3000',
];
let [origin] = acceptedOrigins;
if (acceptedOrigins.includes(req.headers.origin)) origin = req.headers.origin;
res.set({
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'DELETE',
});
if (process.env.NODE_ENV === 'dev' && req.method === 'OPTIONS') {
return res.sendStatus(200);
} else {
next();
}
});
Run Code Online (Sandbox Code Playgroud)
前端
import axios from 'axios';
axios.defaults.withCredentials = true;
let API_ROOT = 'http://127.0.0.1:3001/api';
export const Account = {
endpoints: {
login: `${API_ACCOUNT}/login`,
resendVerification(id) {
return `${API_ACCOUNT}/verify/resend?id=${id}`;
},
},
login(body) {
return axios.post(this.endpoints.login, body);
},
resendVerification(id) {
return axios.get(this.endpoints.resendVerification(id), {
withCredentials: true,
});
},
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1658 次 |
| 最近记录: |