2012-06-05 6 views
3

기본적으로 로그인 양식에서 게시물에 대해 작동하는 다음 경로가 있습니다. 문제는 로그인이 성공하고 (구성원이 발견되고 암호가 일치하는 경우) member._id가 세션에 저장되지 않는다는 것입니다.Node.js의 Express에 세션이 저장되지 않습니다.

내 경로 :

app.post('/signin', function(req, res) { 
    Member.findOne({username: req.body.username}, function(error, member) { 
     var matchPassword = crypto.createHmac('sha1', member.salt).update(req.body.password).digest('hex'); 
     if(member.password == matchPassword) { 
      req.session.member_id = member._id; 
      res.redirect('/' + member.username); 
     } 
    }); 
    res.redirect('/'); 
}); 

나는이 경로는 해고 콘솔에서 다음과 같은 오류 얻을 :

node.js:134 
     throw e; // process.nextTick error, or 'error' event on first tick 
     ^
Error: Can't set headers after they are sent. 
    at ServerResponse.<anonymous> (http.js:527:11) 
    at ServerResponse.setHeader (/Users/admin/Node Projects/sandboxProject/node_modules/express/node_modules/connect/lib/patch.js:62:20) 
    at ServerResponse.header (/Users/admin/Node Projects/sandboxProject/node_modules/express/lib/response.js:280:8) 
    at ServerResponse.redirect (/Users/admin/Node Projects/sandboxProject/node_modules/express/lib/response.js:413:10) 
    at Promise.<anonymous> (/Users/admin/Node Projects/sandboxProject/app.js:109:8) 
    at Promise.<anonymous> (/Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/promise.js:120:8) 
    at Promise.<anonymous> (events.js:64:17) 
    at Promise.emit (/Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/promise.js:59:38) 
    at Promise.complete (/Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/promise.js:70:20) 
    at /Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/query.js:1087:15 

'(그것은 "res.redirect을 좋아하지 않는 것으로 보인다을/'+ member.username); " "req.session.member_id = member._id;"다음에. 이것이 존재하는 몽구스 findOne 콜백의 비동기 특성 때문입니까? 콜백에서 res.redirect를 제거하려고했지만 세션 데이터가 저장되지 않고 거기에두면 "헤더가 이미 전송되었습니다"라는 오류가 발생합니다.

내 구성 :

app.configure(function(){ 
    app.set('views', __dirname + '/views'); 
    app.set('view engine', 'jade'); 
    app.use(express.cookieParser()); 
    app.use(express.session({ secret: "blahblah" })); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(app.router); 
    app.use(express.static(__dirname + '/public')); 
}); 
+0

이 문제를 해결했습니다 :

이 내 질문입니다! Mongoose의 콜백이 비동기이며 "res.redirect ('/');" 내 이전의 깨진 버전의 경로. 콜백 내에서 실패를 처리하고 "res.redirect ('/');"를 삭제하면됩니다. 경로 콜백의 끝에서. 죄송합니다. –

+0

아래 해결 방안이 효과가 있다면, 같은 문제를 가진 다른 사람들을 돕기 위해 올바른 대답으로 하나를 선택할 수 있습니까? – Brandon

답변

8

나는 비슷한 문제가 있었다. 내 문제는 내가 세션에서 뭔가를 삭제했을 때였지만. delete req.session.user, 재로드 및 노드 응용 프로그램 재시작 후에도 계속 남아 있습니다. 그것은 req.session.destroy() 후에 만 ​​사라질 것입니다.

노드의 세션 middleware docs을 살펴본 결과 Session#save() 메서드가있는 것으로 나타났습니다. 그래서 나는 세션 객체 조작 후 req.session.save()을했는데 내 문제를 해결했다. 그것을 시도하고 그것이 당신을 고칠 수 있는지보십시오.

+0

이 답변은 올바른 방향으로 지적했지만 req.session.save()는 콜백을 매개 변수로 사용하는 비동기 함수임을 명시하고 있습니다. 따라서 저장시 데이터에 의존하는 것은 콜백 내에서 실행되어야합니다. 이것은 개발을 위해 메모리 스토리지를 사용하고 "in-time"동작이 발생할 때 일반적으로 명확하지 않습니다. –

4

문제는 Member.findOne이 비동기입니다. 콜백이 실행될 때까지 res.redirect('/')이 이미 실행되었으며 적절한 HTTP 응답 헤더가 설정됩니다. HTTP 규칙에 따라 머리글을 두 번 보낼 수 없으므로 오류 Can't set headers after they are sent.

redirect('/')을 암호 일치의 else 블록으로 옮길 수 있습니다.

관련 문제