web-dev-qa-db-ja.com

ExpressはCookieを設定しません

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});
_

_src/server/main.js_に_cookie-parser_を最初のミドルウェアとして登録しました

_app.use(cookieParser());
_

_/api/v1/auth/login_ルートの応答ヘッダーには

_Set-Cookie:token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ.. 
_

が、Cookieはブラウザに保存されません(_document.cookie_は空です、develepoersツールの_Resources - Cookies_タブも空です): (

EDIT:_/api/v1/auth/login_でこれを呼び出すと(_res.send_または_res.json_を呼び出さずに)

res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999), httpOnly: false});next();

その後、Cookieが設定されますそして、応答ヘッダーは_X-Powered-By:Este.js_を設定します...これは expresでesteMiddlewareを設定しますフロントエンドレンダリングパーツ

_res.send_を使用する場合

_res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999), httpOnly: false}).send({user, token: jwt.token});`
next();
_

sendメソッドが使用されているため、エラー_Can't set headers after they are sent._が表示され、フロントエンドレンダーがこのエラーをスローします。

しかし、APIからデータを送信する必要があるので、これにどのように対処できますか?

助けてもらえますか?ありがとう!

16
Mira

同じ問題がありました。サーバーの応答には、Cookieが設定されています。

Set-Cookie:my_cookie=HelloWorld; Path=/; Expires=Wed, 15 Mar 2017 15:59:59 GMT 

しかし、クッキーはブラウザによって保存されませんでした。

これは私がそれを解決した方法です。

クライアント側のコードでfetchを使用しています。 fetchオプションでcredentials: 'include'を指定しない場合、Cookieはサーバーに送信されず、ブラウザーによって保存されませんが、サーバーの応答はCookieを設定します。

例:

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'
    })
})

それが誰かを助けることを願っています。

29
Green

私はエクスプレス4とノード7.4と角度で作業しますが、これを助ける同じ問題がありました:
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();
 });  

これはすべてのルーターの前になければなりません
このヘッダーがたくさん追加されました:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

しかし、私はそれを必要としません、

b)Cookieを定義するときに、次のようにhttpOnly:falseを追加します。

 res.cookie( key, value,{ maxAge: 1000 * 60 * 10, httpOnly: false });

c)クライアント側:ajaxを送信するには、次のように追加する必要があります: "withCredentials:true、" like:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

がんばろう。

5
izik f

いくつかの問題があります:

  • _httpOnly : false_で明示的に設定されていないCookieは、ブラウザーの_document.cookie_からnotアクセスできます。 HTTPリクエストとともに送信されます。ブラウザの開発ツールをチェックすると、おそらくCookieが見つかります(Chromeでリソース開発ツールのタブ);
  • 呼び出しているnext()は、アプリケーションの他の部分への応答の送信を延期したい場合にのみ使用する必要があります。これは、コードによって判断したものではありません。

だから、これはあなたの問題を解決するはずです:

_res.cookie('token', jwt.token, {
  expires  : new Date(Date.now() + 9999999),
  httpOnly : false
});
res.status(200).send({ user, token: jwt.token });
_

サイドノートとして:httpOnlyがデフォルトでtrueになっている理由があります(悪意のあるXSSスクリプトがセッションCookieなどにアクセスするのを防ぐため)。クライアント側のJSを介してCookieにアクセスできる十分な理由がない場合は、falseに設定しないでください。

2
robertklep

Cookieのサイズを再確認してください。

私にとって、Cookieに保存する認証トークンを生成する方法は、その後のログイン試行でCookieのサイズを大きくし、最終的にブラウザが大きすぎるためにCookieを設定しないようにしました。

ブラウザCookieサイズのチートシート

1
Mr Derfenstien
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')
            })
        }) 
    })
});

応答

res.cookie( 'auth'、user.token).send( 'ok')

サーバーは応答を許可しますが、Cookieはブラウザに保存されません

解決策:

Postman Interceptor Extensionをchromeに追加します。これにより、PostmanはブラウザにCookieを保存し、リクエストの使用を取り戻すことができます。

0
Prakash Karena