发送到客户端后无法设置标头

Posted

技术标签:

【中文标题】发送到客户端后无法设置标头【英文标题】:Cannot set headers after they are sent to the client 【发布时间】:2018-05-25 00:34:57 【问题描述】:

标头发送到客户端后无法设置。这是身份验证发布请求后我的后端错误。看起来有问题 标题。我很抱歉我的项目的脏代码我需要做其他事情,所以评论中有一些代码。 这是我的代码

const express = require("express");
const router = express.Router();
const Spec = require("../models/specialist");
const jwt = require("jsonwebtoken");
const config = require("../config/data");
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;


router.get("/login",(req,res)=>
    res.render("login");
);
router.get("/signup",(req,res)=>
    res.render("signup");
);

    //Registration route
router.post("/spec/register",(req,res)=>
        let date=new Date();
        let newUser = new Spec(
            name:req.body.spec_name,
            email_num:req.body.spec_email,
            password:req.body.spec_password,
            role:"User",
            isActive:true,
            created:date,
            updatedToken:"JWT"

        );
        Spec.addUser(newUser,(err,user)=>
            if(err)
                console.log("err");
               else 
                res.header("Content-Type","application/json");
            //    res.redirect("/users/login");

              
        );


    );

// passport.use(new LocalStrategy(
//     function(username, password, done) 
//      Spec.getUser(username, function(err, user)
//          if(err) return console.error(err.stack);
//          if(!user)
//              return done(null, false, message: 'Unknown User');
//          

//          Spec.comparePassword(password, user.password, function(err, isMatch)
//              if(err) return console.error(err.stack);
//              if(isMatch)
//                  return done(null, user);
//               else 
//                  return done(null, false, message: 'Invalid password');
//              
//          );
//      );
//     ));

//   passport.serializeUser(function(user, done) 
//     done(null, user.id);
//   );

//   passport.deserializeUser(function(id, done) 
//     User.getUserById(id, function(err, user) 
//       done(err, user);
//     );
//   );

     //Authentication route
router.post('/spec/authenticate', (req, res,next) => 
        const email = req.body.email;
        const password = req.body.password;

        Spec.getUser(email, (err, user) => 
          if(err) throw err;
          if(!user)
            return res.json(success: false, msg: 'User not found');
          

          Spec.comparePassword(password, user.password, (err, isMatch) => 
            if(err) throw err;
            if(isMatch)
              let payload=
                name:user.name,
                email:user.email_num,
                role:user.role,
                deleted:user.deleted,
                isActive:user.isActive,
                created:user.created
              ;
              let token = jwt.sign(payload,config.JWT_SECRET,
                  expiresIn:1440
              )

              Spec.saveToken(email,token,(err,success)=>
                if(err) return err;
                console.log("Success");
                // res.setHeader('Authorization','bearer '+token );
                res.cookie('Authorization','bearer '+token);
                res.json ( success: true, token: 'bearer ' + token );
                res.redirect("/users/user");
              ); 


             else 
              return res.json(success: false, msg: 'Wrong password');
            
      );
   );
// res.redirect("/user");
 );
router.get("/user",passport.authenticate('jwt',session:false), (req,res)=>

    res.render("user");
);
router.get("/forgotPass",(req,res)=>
    res.render("forgotPass");
);
router.get("/we",(req,res)=>
    res.render("we");
);


module.exports = router;

你可以在我的代码中找到其他错误,因为我尝试了很多不同的方法。这里是 passport.js 配置文件

const JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
const config = require("./data");
const mongoose = require("mongoose");
const User = require("../models/specialist");

module.exports = function(passport)
    let cookieExtractor = function(req) 
        var token = null;
        if (req && req.cookies)
        
            token = req.cookies['Authorization'];
        
        return token;
    ;
    let opts = 
    opts.jwtFromRequest = cookieExtractor;
    opts.secretOrKey = config.JWT_SECRET;
    passport.use(new JwtStrategy(opts, function(jwt_payload, done) 
        User.findOne(name:jwt_payload._doc.name, function(err, user) 
            if (err) 
                console.log(err);
                return done(err, false);
            
            if (user) 
                console.log("OK 200");
                return done(null, user);
             else 
                console.log("no user");
                return done(null, false);
                // or you could create a new account
            
        );
    ));



//   // Google OAuth Strategy
//   passport.use('googleToken', new GooglePlusTokenStrategy(
//     clientID: config.oauth.google.clientID,
//     clientSecret: config.oauth.google.clientSecret
//   , async (accessToken, refreshToken, profile, done) => 
//     try 
//       // Should have full user profile over here
//       console.log('profile', profile);
//       console.log('accessToken', accessToken);
//       console.log('refreshToken', refreshToken);

//       const existingUser = await User.findOne( "google.id": profile.id );
//       if (existingUser) 
//         return done(null, existingUser);
//       

//       const newUser = new User(
//         method: 'google',
//         google: 
//           id: profile.id,
//           email: profile.emails[0].value
//         
//       );

//       await newUser.save();
//       done(null, newUser);
//      catch(error) 
//       done(error, false, error.message);
//     
//   ));

//   passport.use('facebookToken', new FacebookTokenStrategy(
//     clientID: config.oauth.facebook.clientID,
//     clientSecret: config.oauth.facebook.clientSecret
//   , async (accessToken, refreshToken, profile, done) => 
//     try 
//       console.log('profile', profile);
//       console.log('accessToken', accessToken);
//       console.log('refreshToken', refreshToken);

//       const existingUser = await User.findOne( "facebook.id": profile.id );
//       if (existingUser) 
//         return done(null, existingUser);
//       

//       const newUser = new User(
//         method: 'facebook',
//         facebook: 
//           id: profile.id,
//           email: profile.emails[0].value
//         
//       );

//       await newUser.save();
//       done(null, newUser);
//      catch(error) 
//       done(error, false, error.message);
//     
//   ));

  // LOCAL STRATEGY
//   module.exports = function(passport)
//   passport.use(new LocalStrategy(
//     function(username, password, done) 
//      Spec.findOne( username: username , function (err, user) 
//         if (err)  return done(err); 
//         if (!user)  return done(null, false); 
//         if (!user.verifyPassword(password))  return done(null, false); 
//         return done(null, user);
//       );
//     
//   ));
// 

这是认证的ajax请求

$('.logInForm').on('submit', function (e) 
            $.ajax(
                type: 'post',
                url: 'http://localhost:3000/users/spec/authenticate',
                data: $(this).serialize(),
                success:function(data)
                    console.log(data);
                    localStorage.setItem("authToken",data.token);
                    
            ).done(function(data)
                if(data.token)
                    location.href="http://localhost:3000/users/user";
                else
                    console.log("err");
                
            );
            e.preventDefault();
        );

非常感谢。

【问题讨论】:

哪个特定操作给您带来了错误? 出现该错误的身份验证后响应 Error: Can't set headers after they are sent to the client的可能重复 【参考方案1】:

这是由于您的代码尝试从身份验证函数发送多个响应。

res.json ( success: true, token: 'bearer ' + token ); // 1st Response
res.redirect("/users/user"); // 2nd Response

删除其中一个您不使用的。

【讨论】:

以上是关于发送到客户端后无法设置标头的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS "发送到客户端 NodeJS 后无法设置标头"

Post Request express:发送到客户端后无法设置标头

http POST响应后,发送到客户端后无法设置标头

Node.js 发送到客户端后无法设置标头

Express: [ERR_HTTP_HEADERS_SENT]: 发送到客户端后无法设置标头

ERR_HTTP_HEADERS_SENT - Express:标头在发送到客户端后无法设置,我该如何解决这个错误?