2017-02-24 191 views
2

我遇到Node Express和CSurf的問題 - 403(禁止)無效的csrf令牌。通過其他答案看,並嘗試了所有我可以通過搜索找到,我只是無法克服這一點。CSRF 403禁止 - 無效的CSRF令牌

我測試了郵遞員的API,它工作得很好。

當我嘗試在登錄表單上使用它時,它不起作用。

代碼後端:

var express = require('express'); 
var path = require('path'); 
var favicon = require('serve-favicon'); 
var logger = require('morgan'); 
var cookieParser = require('cookie-parser'); 
var bodyParser = require('body-parser'); 
// var session = require('client-sessions'); 
var session = require('express-session'); 
var flash = require('connect-flash'); 
var csrf = require('csurf'); 
var cors = require('cors'); 

//======== newly added ===== 
// var csrfProtection = csrf({ cookie: true }); 

//==== end of all ========== 

// var RedisStore = require('connect-redis')(session); 

// var fileUpload = require('express-fileupload'); 

var app = express(); 

// app.use(fileUpload()); 

// view engine setup 
app.set('views', path.join(__dirname, 'views')); 
app.set('view engine', 'ejs'); 

// uncomment after placing your favicon in /public 
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 
app.use(logger('dev')); 
app.use(bodyParser.json()); 
app.use(bodyParser.json({limit: '100mb'})); 
app.use(bodyParser.urlencoded({limit: '100mb', extended: true, parameterLimit:50000})); 
app.use(cors()); 
app.options('*', cors()); 
app.use(cookieParser()); 

app.set('trust proxy', 1) // trust first proxy 
app.use(session({ 
    secret : 'irutirutiurtuiru', 
    expires : new Date(Date.now() + 3600000), 
    resave : false, 
    saveUninitialized : true, 
})); 
app.use(flash()); 

//To disable x-powered-by details in header 
app.disable('x-powered-by'); 
app.use(csrf({ cookie: true })); 



var index = require('./routes/index'); 
var users = require('./routes/users'); 
var tags = require('./routes/tags'); 
var access = require('./routes/access'); 
var brand = require('./routes/brand'); 
var user = require('./routes/user'); 
var article = require('./routes/article'); 
var articlenew = require('./routes/articlenew'); 
// var imageUpload = require('./routes/imageUpload'); 
var faq = require('./routes/faq'); 
var login = require('./routes/login'); 
var admin = require('./routes/admins'); 
var editorpick = require('./routes/editorpick'); 
var log = require('./routes/log'); 
var articleadminview = require('./routes/articleadminview'); 
var logout = require('./routes/logout'); 
var domain = require('./routes/domain'); 

var banner = require('./routes/banner'); 
var bannerview = require('./routes/bannerview'); 
var moderater = require('./routes/moderater'); 
var poll = require('./routes/poll'); 
var articleviewcount = require('./routes/articleviewcount'); 
var report = require('./routes/report'); 
var whitepaper = require('./routes/whitepaper'); 
var changepassword = require('./routes/changepassword'); 
var editprofile = require('./routes/editprofile'); 


app.use(require('stylus').middleware(path.join(__dirname, 'public'))); 
app.use(express.static(path.join(__dirname, 'public'))); 

app.use('/', index); 
// app.use('/users', users); 
app.use('/tags',tags); 
app.use('/access', access); 
app.use('/brand', brand); 
app.use('/user', user); 
app.use('/article', article); 
app.use('/articlenew', articlenew); 
// app.use('/imageUpload', imageUpload); 
app.use('/faq', faq); 
app.use('/login', login); 
app.use('/admins', admin); 
app.use('/editorpick', editorpick); 
app.use('/log', log); 
app.use('/articleadminview', articleadminview); 
app.use('/logout', logout); 
app.use('/domain', domain); 
app.use('/banner', banner); 
app.use('/bannerview', bannerview); 
app.use('/moderater', moderater); 
app.use('/poll', poll); 
app.use('/articleviewcount',articleviewcount); 
app.use('/report', report); 
app.use('/whitepaper', whitepaper); 
app.use('/changepassword', changepassword); 
app.use('/editprofile', editprofile); 


//client session 
// app.use(session({ 
// cookieName: 'session', 
// secret: 'random_string_goes_here', 
// duration: 30 * 60 * 1000, 
// activeDuration: 5 * 60 * 1000, 
// })); 

// app.use(session({ 
// secret: 'fnss0893oin$(@&', 
// resave: false, 
// saveUninitialized: true 
// })); 


// catch 404 and forward to error handler 
app.use(function(req, res, next) { 

    // res.header("Access-Control-Allow-Origin", "*"); 
    // res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 

    var err = new Error('Not Found'); 
    err.status = 404; 
    next(err); 
}); 

// error handler 
app.use(function(err, req, res, next) { 
    // set locals, only providing error in development 
    res.locals.message = err.message; 
    res.locals.error = req.app.get('env') === 'development' ? err : {}; 



    res.locals._csrf = req.csrfToken(); 
    // if(err.code == 'EBADCSRFTOKEN'){ 
    // res.render('csrfError'); 
    // } 

    // render the error page 
    res.status(err.status || 500); 
    // res.render('404'); 
    res.render('error'); 
}); 

module.exports = app; 

代碼前端:

$(function(){ 
    loginPage(); 
}); 
function loginPage(){ 
    $('#footer').load('footer', function(){ 
     $('.footer').addClass('posAbs'); 
    }); 

    $('.preloader').fadeOut(); 

    $(document).on('click', '#signin', function() { 
     //Retreving the input values 
     login(); 
    }); 
    $("#loginpass").on("keydown", function(event) { 
     if(event.which == 13){ 
     login(); 
     } 
    }); 
    $('.forgot-btn').on('click', function(){ 
      $(".loginContainer").fadeOut(400, function(){ 
      $(".resetContainer").fadeIn(400); 
     }); 
    }); 
    $('.resetpass-btn').on('click', function(){ 
     forgotPass(); 
    }); 
    $(".emailId").on("keydown", function(event) { 
     if(event.which == 13){ 
      forgotPass(); 
     } 
    }); 
    $('.notifycontent, .submitted').hide(); 
    $('.notifya').on('click', function(){ 
     $('.notifyMain').hide(); 
     $('.notifycontent').show(); 
    }) 
    $(document).on('click', '.notifysubmit', function(){ 
     var email = $('#notifyEmail').val(); 
     if(email == ""){ 
      var h = $('#notifyEmail').parent().find('.highlighter'); 
      h.show(); 
      h.addClass('shake animated'); 
      $('#notifyEmail').addClass('error'); 
      h.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 
       $(this).removeClass("shake animated"); 
       setTimeout(function() { 
        h.fadeOut(300); 
       }, 5000); 
      }); 
      return false; 
     } 
     else if(email != ""){ 
      var expr = /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/; 
      if(!expr.test(email)){ 
       var h = $('#notifyEmail').parent().find('.highlighter'); 
       h.show().html('Enter a valid Email'); 
       h.addClass('shake animated'); 
       $('#notifyEmail').addClass('error'); 
       h.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 
        $(this).removeClass("shake animated"); 
        setTimeout(function() { 
         h.fadeOut(300); 
        }, 5000); 
       }); 
       return false; 
      } 
      else{ 
       mailAdmin(email); 
       $('#notifyadmin').modal('hide'); 
      } 

     } 

    }); 
    inputValidate(); 
} 
function loginerror() { 
    var email = $('.email').val(); 
    var password = $('.password').val(); 
    if(email == ''){ 
    var h = $('.email').parent().find('.highlighter'); 
     h.show(); 
     h.addClass('shake animated'); 
     $('.email').addClass('error'); 
     h.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 
      $(this).removeClass("shake animated"); 
      setTimeout(function() { 
       h.fadeOut(300); 
      }, 5000); 
     }); 

    } 
    else if(password == ''){ 
     var h = $('.password').parent().find('.highlighter'); 
     h.show(); 
     h.addClass('shake animated'); 
     $('.password').addClass('error'); 
     h.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 
      $(this).removeClass("shake animated"); 
      setTimeout(function() { 
       h.fadeOut(300); 
      }, 5000); 
     }); 
    } 
} 
function forgotPass(){ 
     var emailId = $('.emailId').val(); 
     var emailRegex = new RegExp(/^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$/i); 
     var valid = emailRegex.test(emailId); 
      if (!valid) { 
      var h = $('.emailId').parent().find('.highlighter'); 
      h.show(); 
      h.addClass('shake animated'); 
      $('.emailId').addClass('error'); 
      h.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 
       $(this).removeClass("shake animated"); 
       setTimeout(function() { 
        h.fadeOut(300); 
       }, 5000); 
      }); 
      return false; 
      } else{ 
      $('.preloader').fadeIn(300); 
       forgotPassword(emailId); 
      } 
} 
function forgotPassword(email){ 
    var settings = { 
     "url": base_url+"/forgotpassword/"+email, 
     "method": "GET", 
     "async" : true, 
    }; 
    $.ajax(settings).done(function(data) { 
     if (data.status === true) { 
       $('#resetPass h4').html('Your password reset link has been mailed to '+email); 
       $('.preloader').fadeOut(300); 
       $('#resetPass').modal('show'); 
       pageCheck = "reset" 
      } 

     else { 
      checkactiveUser(email, pageCheck); 
     } 

    }).fail(function(jqXHR, textStatus, errorThrown) { 
     if (jqXHR.status == 403 || jqXHR.status == 405) { 
      console.log('Server error. ' + jqXHR.status + '. ' + textStatus + '. ' + errorThrown); 
      forgotPassword(); 
     } 
     console.log('Server error. Please try again.'); 
    }); 
} 

function login(){ 
    var email = $('.email').val(); 
     var password = $('.password').val(); 
     var csrfToken = fetchtoken(); 
     pageCheck = "login" 
     if ((email != '') && (password != '')) {   
      var settings = { 
       "url": base_url+"/login", 
       "method": "POST", 
       dataType: 'json', 
       // headers: { 
       //  "x-CSRF-token": csrfToken, 
       // }, 
       data:{ 
        "email": email, 
        "password": password, 
        // "_csrf": csrfToken 
       }, 
       crossdomain : true 
      }; 
      $.ajax(settings).done(function(data) { 
       if (data.status === true) { 
        alert(); 
        // var data = data.data; 
        // token = data.accesstoken; 
        // var userId = data.id; 
        // localStorage.setItem('userId', userId); 
        // localStorage.setItem('token', token); 
        // var userInfo = JSON.stringify(data); 
        // localStorage.setItem('pollVisited', data.pollVisitedFlag); 
        // window.open('home', '_self'); 
       } 
       else { 
        if(data.msg == "Email id doesnt exist"){ 
         $('#loginError').modal('show'); 
        } 
        else{ 
         $('.preloader').fadeIn(); 
         checkactiveUser(email, pageCheck); 
         // var h = $('.password').parent().find('.highlighter'); 
         // h.show().html('Enter a valid password'); 
         // h.addClass('shake animated'); 
         // $('.password').addClass('error'); 
         // h.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 
         //  $(this).removeClass("shake animated"); 
         //  setTimeout(function() { 
         //   h.fadeOut(300); 
         //  }, 5000); 
         // }); 
        } 

       } 
      }).fail(function(jqXHR, textStatus, errorThrown) { 
       if (jqXHR.status == 403 || jqXHR.status == 405 || jqXHR.status == 502) { 
        console.log('Server error. ' + jqXHR.status + '. ' + textStatus + '. ' + errorThrown); 
        loginPage(); 
       } 
       console.log(jqXHR.status + textStatus + errorThrown); 
      }); 

     } else { 
      loginerror(); 
     } 
} 
function inputValidate(){ 
    $('input').focus(function(){ 
     $(this).removeClass('error'); 
     $('.highlighter').fadeOut(300); 
    }); 
} 
function logintimeLog(token){ 
    var settings = { 
       "url": base_url+"/logintimelog/"+ token, 
       "method": "GET", 
      }; 
    $.ajax(settings).done(function(data) { 
     if (data.status === true) { 
      console.log('log in'); 
     } else { 
      console.log('Response status is false'); 
      logintimeLog(); 
     } 
    }).fail(function(jqXHR, textStatus, errorThrown) { 
     if (jqXHR.status == 403 || jqXHR.status == 405 || jqXHR.status == 502) { 
      console.log('Server error. ' + jqXHR.status + '. ' + textStatus + '. ' + errorThrown); 
      logintimeLog(); 
     } 
     console.log('Server error. Please try again.'); 
     logintimeLog(); 
    }); 
} 

function checkactiveUser(email, x){ 
    var settings = { 
     "url": base_url+"/userexist", 
     "method": "POST", 
     data:{ 
      "email": email, 
     } 
    }; 
     $.ajax(settings).done(function(data) { 
      if (data.status === true) { 
       if(data.active === 0){ 
        $('.verify-btn').attr('disabled', true).removeClass('green').addClass('disabled'); 
        $('#onboarding h4').html('Your account is verified.'); 
        $('#onboarding p').html('Complete your sign-up to start using RMA.'); 
        $('#onboarding .sign-here').hide(); 
        $('#onboarding .black-filled').html('Okay'); 
        $('#onboarding').modal('show'); 
        $('.preloader').fadeOut(300); 
       } 
       else{ 
         if(x == 'login'){ 
          $('.preloader').fadeOut(300); 
          var h = $('.password').parent().find('.highlighter'); 
          h.show().html('Enter a valid password'); 
          h.addClass('shake animated'); 
          $('.password').addClass('error'); 
          h.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 
           $(this).removeClass("shake animated"); 
           setTimeout(function() { 
            h.fadeOut(300); 
           }, 5000); 
          }); 
         } 
         else{ 
          $('.preloader').fadeOut(300); 
          $('#onboarding').modal('show'); 
         } 
        }  
       } 
       else{ 
        if(x == "reset"){ 
         $('#notifyadmin').modal('show'); 
        } 
        if(x == 'login'){ 
         var h = $('.password').parent().find('.highlighter'); 
         h.show().html('Enter a valid password'); 
         h.addClass('shake animated'); 
         $('.password').addClass('error'); 
         h.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 
          $(this).removeClass("shake animated"); 
          setTimeout(function() { 
           h.fadeOut(300); 
          }, 5000); 
         }); 
        } 

       } 
     }).fail(function(jqXHR, textStatus, errorThrown) { 
      if (jqXHR.status == 403 || jqXHR.status == 405) { 
       console.log('Server error. ' + jqXHR.status + '. ' + textStatus + '. ' + errorThrown); 
       emailVerification(); 
      } 
      console.log('Server error. Please try again.'); 
     });  
} 
function mailAdmin(email){ 
    $('.preloader').fadeIn(); 
    var settings = { 
     "url": base_url+"/mailtoadmin", 
     "method": "POST", 
     data:{ 
      "email": email, 
     } 
    }; 
     $.ajax(settings).done(function(data) { 
      if (data.status === true) { 
        $('.notifycontent').hide(); 
        $('.submitted').show(); 
        $('#notifyadmin').modal('show'); 
        $('.preloader').fadeOut(); 

       } 
     }).fail(function(jqXHR, textStatus, errorThrown) { 
      if (jqXHR.status == 403 || jqXHR.status == 405) { 
       console.log('Server error. ' + jqXHR.status + '. ' + textStatus + '. ' + errorThrown); 
       emailVerification(); 
      } 
      console.log('Server error. Please try again.'); 
     });  
} 
function fetchtoken(){ 
    var settings = { 
     "url": base_url+"/fetchtoken", 
     "method": "GET", 
    }; 
     $.ajax(settings).done(function(data) { 
      $('input[name="_csrf"]').val(data.token); 
      return data.token; 
     }).fail(function(jqXHR, textStatus, errorThrown) { 
      if (jqXHR.status == 403 || jqXHR.status == 405) { 
       console.log('Server error. ' + jqXHR.status + '. ' + textStatus + '. ' + errorThrown); 
       fetchtoken(); 
      } 
      console.log('Server error. Please try again.'); 
     }); 
} 

UPDATE:響應頭[/ fetchtoken]

HTTP/1.1 200 OK 
Server: nginx 
Date: Sat, 25 Feb 2017 13:14:44 GMT 
Content-Type: application/json; charset=utf-8 
Content-Length: 48 
Connection: keep-alive 
Access-Control-Allow-Origin: * 
set-cookie: _csrf=2bd-cKtDQuEeKrACQAJr-Rhu; Path=/ 
set-cookie: connect.sid=s%3AMIz1TNRpYTI7Pk8uO6MgzOd5M6a31cyW.0RYKkWw9w6om7GGQSawE89hDskJJ5nQ7HZdI24jdmF8; Path=/; HttpOnly 
ETag: W/"30-GhAlz0fz9nu44Q5ZUCXJSw" 
Cache-Control: max-age=0, no-cache, no-store, must-revalidate 
Pragma: no-cache 
X-Xss-Protection: 1; mode=block 
X-Frame-Options: SAMEORIGIN 
X-Content-Type-Options: nosniff 

UPDATE:響應頭[登錄]

HTTP/1.1 403 Forbidden 
Server: nginx 
Date: Sat, 25 Feb 2017 13:14:44 GMT 
Content-Type: text/html; charset=utf-8 
Transfer-Encoding: chunked 
Connection: keep-alive 
Access-Control-Allow-Origin: * 
set-cookie: _csrf=WOF-6ruV7OretakTDESz0gdv; Path=/ 
set-cookie: connect.sid=s%3A6ft632U8-ykvlzSrUiPcBM4ULBHtIl_A.FuiSoiQ6%2BC22ThR%2Br5PwwHgCLP1nve2mFSLwoluLJTs; Path=/; HttpOnly 
ETag: W/"445-JIguc6Asgpp7T6tcOBhH9w" 
Content-Encoding: gzip 

HTML元素:

<input id="_csrf" type="hidden" value="1Lf4MPRe-vaeSnvXKNmDIlGIBx4epL6izVFA" name="_csrf"> 
+0

早些時候,我在CORS問題,因爲前端frontend.mysite.com和API是backend.mysite.com – Zed

+2

可能重複的[Node Express和csurf - 403(Forbidden)無效的csrf標記](http://stackoverflow.com/questions/33849252/node-express-and-csurf-403-forbidden-invalid -csrf-token) –

+0

我有t說了這一點,它並沒有解決我的問題@MikeMcCaughan – Zed

回答

0

您使用的是fetchtoken功能,如果它是同步的,當它實際上是異步的。

嘗試用替換fetchtoken功能:

function fetchtoken(){ 
    var settings = { 
     "url": base_url+"/fetchtoken", 
     "method": "GET", 
    }; 
     return $.ajax(settings).done(function(data) { 
      return data.token; 
     }).fail(function(jqXHR, textStatus, errorThrown) { 
      if (jqXHR.status == 403 || jqXHR.status == 405) { 
       console.log('Server error. ' + jqXHR.status + '. ' + textStatus + '. ' + errorThrown); 
       return fetchtoken(); 
      } 

      return null; 
      console.log('Server error. Please try again.'); 
     }); 
} 

,取而代之的login功能:

function login(){ 
    var email = $('.email').val(); 
    var password = $('.password').val(); 
    pageCheck = "login" 
    fetchtoken().then(function(csrfToken) { 
     if ((email != '') && (password != '')) {   
      var settings = { 
       "url": base_url+"/login", 
       "method": "POST", 
       dataType: 'json', 
       data:{ 
         "email": email, 
        "password": password, 
        "_csrf": csrfToken 
       }, 
       crossdomain : true 
      }; 
      $.ajax(settings).done(function(data) { 
       if (data.status === true) { 
        alert("Logged in!"); 
        // var data = data.data; 
        // token = data.accesstoken; 
        // var userId = data.id; 
        // localStorage.setItem('userId', userId); 
        // localStorage.setItem('token', token); 
        // var userInfo = JSON.stringify(data); 
        // localStorage.setItem('pollVisited', data.pollVisitedFlag); 
        // window.open('home', '_self'); 
       } 
       else { 
        if(data.msg == "Email id doesnt exist"){ 
         $('#loginError').modal('show'); 
        } 
        else{ 
         $('.preloader').fadeIn(); 
         checkactiveUser(email, pageCheck); 
         // var h = $('.password').parent().find('.highlighter'); 
         // h.show().html('Enter a valid password'); 
         // h.addClass('shake animated'); 
         // $('.password').addClass('error'); 
         // h.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 
         //  $(this).removeClass("shake animated"); 
         //  setTimeout(function() { 
         //   h.fadeOut(300); 
         //  }, 5000); 
         // }); 
        } 
       } 
      }).fail(function(jqXHR, textStatus, errorThrown) { 
       if (jqXHR.status == 403 || jqXHR.status == 405 || jqXHR.status == 502) { 
        console.log('Server error. ' + jqXHR.status + '. ' + textStatus + '. ' + errorThrown); 
        loginPage(); 
       } 
       console.log(jqXHR.status + textStatus + errorThrown); 
      }); 
     } else { 
      loginerror(); 
     } 
    }); 
} 
+0

謝謝你的支持和幫助我。 我只是嘗試了你推薦的任何東西,但不幸的是我得到了同樣的錯誤。 – Zed

+0

@ZeeS請在'if((email!='')&&(password!='')){' - 之前加上一個'console.log(csrfToken)',看它是否打印出來。 – thesbros

+0

對象{令牌: 「18GRH1wc-NpR7SR2fZIx6rfUNoZXP9q0VUCs」}的令牌: 「18GRH1wc-NpR7SR2fZIx6rfUNoZXP9q0VUCs」 __ proto__:對象 VM654:2 POST http://api.site.com/login 403(禁止) (匿名)@ VM654:2 發送@ jquery-1.12.0.min.js:4 ajax @ jquery-1.12.0.min.js:4 (匿名)@ login.js:239 (匿名)@ jquery-1.12.0.min。 js:2 i @ jquery-1.12.0.min.js:2 fireWith @ jquery-1.12.0.min.js:2 y @ jquery-1.12.0.min.js:4 c @ jquery- 1.12.0.min.js:4 login.js:272服務器錯誤。錯誤。 Forbidden 登錄。js:275 403errorForbidden – Zed