node.js Express 不设置 cookie
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36824106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Express doesn't set a cookie
提问by Mira
I have problem with setting a cookies via express. I'm using Este.js dev stackand I try to set a cookie in API auth /loginroute. Here is the code that I use in /api/v1/auth/loginroute
我在通过 express 设置 cookie 时遇到问题。我正在使用Este.js dev stack并尝试在 API 身份验证/login路由中设置 cookie 。这是我在/api/v1/auth/login路由中使用的代码
res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999)});
res.status(200).send({user, token: jwt.token});
In src/server/main.jsI have registered cookie-parseras first middleware
在src/server/main.js我注册cookie-parser为第一个中间件
app.use(cookieParser());
The response header for /api/v1/auth/loginroute contains
/api/v1/auth/login路由的响应头包含
Set-Cookie:token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ..
but the cookie isn't saved in browser(document.cookieis empty, also Resources - Cookiestab in develepoers tools is empty) :(
但是 cookie 没有保存在浏览器中(document.cookie是空的,Resources - Cookiesdevelepoers 工具中的选项卡也是空的):(
EDIT:I'm found that when I call this in /api/v1/auth/login(without call res.sendor res.json)
编辑:我发现当我调用它时/api/v1/auth/login(没有调用res.send或res.json)
res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999), httpOnly: false});next();
res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999), httpOnly: false});next();
then the cookie is setAND response header has set X-Powered-By:Este.js... this sets esteMiddlewarein expres frontend rendering part.
然后设置了 cookie 并且设置了响应标头X-Powered-By:Este.js……这esteMiddleware在expres 前端渲染部分中设置。
When I use res.send
当我使用 res.send
res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999), httpOnly: false}).send({user, token: jwt.token});`
next();
then I get error Can't set headers after they are sent.because sendmethod is used, so frontend render throw this error.
然后我得到错误,Can't set headers after they are sent.因为使用了send方法,所以前端渲染抛出这个错误。
But I have to send a data from API, so how I can deal with this?
但是我必须从 API 发送数据,那么我该如何处理呢?
Can some help me please? Thanks!
有人可以帮我吗?谢谢!
回答by Green
I had the same issue. The server response comes with cookie set:
我遇到过同样的问题。服务器响应带有 cookie 集:
Set-Cookie:my_cookie=HelloWorld; Path=/; Expires=Wed, 15 Mar 2017 15:59:59 GMT
But the cookie was not saved by a browser.
但是 cookie 没有被浏览器保存。
This is how I solved it.
我就是这样解决的。
I use fetchin a client-side code. If you do not specify credentials: 'include'in fetchoptions, cookies are neither sent to server nor saved by a browser, although the server response sets cookies.
我fetch在客户端代码中使用。如果您没有credentials: 'include'在fetch选项中指定,cookie 既不会发送到服务器,也不会被浏览器保存,尽管服务器响应设置了 cookie。
Example:
例子:
var headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
return fetch('/your/server_endpoint', {
method: 'POST',
mode: 'same-origin',
redirect: 'follow',
credentials: 'include', // Don't forget to specify this if you need cookies
headers: headers,
body: JSON.stringify({
first_name: 'John',
last_name: 'Doe'
})
})
Hope it helps somebody.
希望它可以帮助某人。
回答by izik f
i work with express 4 and node 7.4 and angular,I had the same problem me help this:
a) server side: in file app.js i give headers to all response like:
我使用 express 4 和 node 7.4 以及 angular,我遇到了同样的问题,我可以帮忙:
a) 服务器端:在文件 app.js 中,我为所有响应提供了标头,例如:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
this must have before all router.
I saw a lot of added this headers:
这必须在所有路由器之前都有。
我看到很多添加了这个标题:
res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
but i dont need that,
b) when you definer cookie you nee add httpOnly: false, like:
但我不需要那个,
b) 当你定义 cookie 时,你需要添加 httpOnly: false,比如:
res.cookie( key, value,{ maxAge: 1000 * 60 * 10, httpOnly: false });
c) client side: in send ajax you need add: "withCredentials: true," like:
c) 客户端:在发送 ajax 中,您需要添加:“withCredentials: true”,例如:
$http({
method: 'POST',
url: 'url,
withCredentials: true,
data : {}
}).then(function(response){
// code
}, function (response) {
// code
});
good luck.
祝你好运。
回答by Deda
Struggling with this for a 3h, and finally realized, with axios, I should set withCredentialsto true, even though I am only receiving cookies.
挣扎了 3 小时,终于意识到,即使我只收到 cookie axios,我也应该设置withCredentials为true。
axios.defaults.withCredentials = true;
axios.defaults.withCredentials = true;
回答by robertklep
There's a few issues:
有几个问题:
- a cookie that isn't explicitly set with
httpOnly : falsewill notbe accessible throughdocument.cookiein the browser. It will still be sent with HTTP requests, and if you check your browsers' dev tools you will most likely find the cookie there (in Chrome they can be found in the Resourcestab of the dev tools); - the
next()that you're calling should only be used if you want to defer sending back a response to some other part of your application, which—judging by your code—is not what you want.
- 未明确设置的 cookie
httpOnly : false将无法document.cookie在浏览器中访问。它仍然会与 HTTP 请求一起发送,如果您检查浏览器的开发工具,您很可能会在那里找到 cookie(在 Chrome 中,它们可以在开发工具的资源选项卡中找到); - 对
next()你,如果你想推迟发送回应用程序,你的这度判断的一些其他部分的响应正在调用应仅用于代码是不是你想要的。
So, it seems to me that this should solve your problems:
所以,在我看来,这应该可以解决您的问题:
res.cookie('token', jwt.token, {
expires : new Date(Date.now() + 9999999),
httpOnly : false
});
res.status(200).send({ user, token: jwt.token });
As a side note: there's a reason for httpOnlydefaulting to true(to prevent malicious XSS scripts from accessing session cookies and the like). If you don't have a very good reason to be able to access the cookie through client-side JS, don't set it to false.
附带说明:httpOnly默认为true(以防止恶意 XSS 脚本访问会话 cookie 等)是有原因的。如果您没有很好的理由能够通过客户端 JS 访问 cookie,请不要将其设置为false.
回答by Mr Derfenstien
Double check the size of your cookie.
仔细检查您的 cookie 的大小。
For me, the way I was generating an auth token to store in my cookie, was causing the size of the cookie to increase with subsequent login attempts, eventually causing the browser to not set the cookie because it's too big.
对我来说,我生成身份验证令牌以存储在我的 cookie 中的方式导致 cookie 的大小随着随后的登录尝试而增加,最终导致浏览器无法设置 cookie,因为它太大了。
回答by Pavel Aslanov
There is no problem to set "httpOnly" to true in a cookie.
在 cookie 中将“httpOnly”设置为 true 没有问题。
I am using "request-promise" for requests and the client is a "React" app, but the technology doesn't matter. The request is:
我对请求使用“request-promise”,客户端是“React”应用程序,但技术无关紧要。请求是:
var options = {
uri: 'http://localhost:4000/some-route',
method: 'POST',
withCredentials: true
}
request(options)
.then(function (response) {
console.log(response)
})
.catch(function (err) {
console.log(err)
});
The response on the node.js (express) server is:
node.js (express) 服务器上的响应是:
var token=JSON.stringify({
"token":"some token content"
});
res.header('Access-Control-Allow-Origin', "http://127.0.0.1:3000");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header( 'Access-Control-Allow-Credentials',true);
var date = new Date();
var tokenExpire = date.setTime(date.getTime() + (360 * 1000));
res.status(201)
.cookie('token', token, { maxAge: tokenExpire, httpOnly: true })
.send();
The client make a request, the server set the cookie , the browser (client) receive it (you can see it in "Application tab on the dev tools") and then I again launch a request to the server and the cookie is located in the request: "req.headers.cookie" so accessible by the server for verifying.
客户端发出请求,服务器设置 cookie,浏览器(客户端)接收它(您可以在“开发工具的应用程序选项卡”中看到它),然后我再次向服务器发出请求,cookie 位于请求:“req.headers.cookie”,以便服务器访问以进行验证。
回答by Prakash Karena
app.post('/api/user/login',(req,res)=>{
User.findOne({'email':req.body.email},(err,user)=>{
if(!user) res.json({message: 'Auth failed, user not found'})
user.comparePassword(req.body.password,(err,isMatch)=>{
if(err) throw err;
if(!isMatch) return res.status(400).json({
message:'Wrong password'
});
user.generateToken((err,user)=>{
if(err) return res.status(400).send(err);
res.cookie('auth',user.token).send('ok')
})
})
})
});
response
回复
res.cookie('auth',user.token).send('ok')
res.cookie('auth',user.token).send('ok')
server gives response ok but the cookie is not stored in the browser
服务器给出响应,但 cookie 未存储在浏览器中
Solution :
解决方案 :
Add Postman Interceptor Extension to chrome which allows postman to store cookie in browser and get back useing requests.
将邮递员拦截器扩展添加到 chrome,它允许邮递员在浏览器中存储 cookie 并返回使用请求。
回答by danday74
A cookie can't be set if the client and server are on different domains. Different sub-domains is doable but not different domains and not different ports.
如果客户端和服务器位于不同的域中,则无法设置 cookie。不同的子域是可行的,但不是不同的域,也不是不同的端口。
If using Angular as your frontend you can simply send all requests to the same domain as your Angular app (so the app is sending all API requests to itself) and stick an /api/ in every HTTP API request URL - usually configured in your environment.ts file:
如果使用 Angular 作为前端,您可以简单地将所有请求发送到与您的 Angular 应用程序相同的域(因此该应用程序将所有 API 请求发送给自己)并在每个 HTTP API 请求 URL 中粘贴 /api/ - 通常在您的环境中配置.ts 文件:
export const environment = {
production: false,
httpPhp: 'http://localhost:4200/api'
}
Then all HTTP requests will use environment.httpPhp + '/rest/of/path'
然后所有的 HTTP 请求都将使用 environment.httpPhp + '/rest/of/path'
Then you can proxy those requests by creating proxy.conf.json as follows:
然后你可以通过创建 proxy.conf.json 来代理这些请求,如下所示:
{
"/api/*": {
"target": "http://localhost:5200",
"secure": false,
"changeOrigin": true,
"pathRewrite": {
"^/api": ""
}
}
}
Then add this to ng serve:
然后将其添加到 ng serve:
ng serve -o --proxy-config proxy.conf.json
Then restart your app and it should all work, assuming that your server is actually using Set-Cookie in the HTTP response headers. (Note, on a diff domain you won't even see the Set-Cookie response header, even if the server is configured correctly).
然后重新启动您的应用程序,它应该一切正常,假设您的服务器实际上在 HTTP 响应标头中使用 Set-Cookie。(请注意,在差异域中,即使服务器配置正确,您也不会看到 Set-Cookie 响应标头)。
回答by Ivan Vovk
One of the main features is to set header correctly.
主要功能之一是正确设置标题。
For nginx:
对于 Nginx:
add-header Access-Control-Allow-Origin' 'domain.com';
add-header Access-Control-Allow-Origin' 'domain.com';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Credentials' 'true';
Add this to your web server.
将此添加到您的 Web 服务器。
Then form cookie like this:
然后像这样形成cookie:
"cookie": {
"secure": true,
"path": "/",
"httpOnly": true,
"hostOnly": true,
"sameSite": false,
"domain" : "domain.com"
}
The best approach to get cookie from express is to use cookie-parser.
从 express 获取 cookie 的最佳方法是使用 cookie-parser。

