2017-05-15 63 views
2

我試圖做一個ajax put請求後的重定向。我打算使用純JS客戶端進行驗證。從AJAX調用res.redirect

客戶:

$(document).ready(function() { 
    login =() => { 
     var username = $("[name='username']").val() 
     var password = $("[name='password']").val() 
     $.ajax({ 
      type: "put", 
      url: '/login', 
      data: { 
       username: username, 
       password: password 
      } 
      // success: function(response) { 
      // console.log('Success:') 
      // console.log(response.user) 

      // Cookies.set('username', response.user.username) 
      // Cookies.set('first_name', response.user.first_name) 
      // Cookies.set('last_name', response.user.last_name) 
      // Cookies.set('email', response.user.email) 

      // window.location.href = window.location.origin + '/' 
      // }, 
      // error: function(error) { 
      // console.log("Error:") 
      // console.log(error) 
      // } 
     }) 
    } 

    logout =() => { 
     console.log("Log out clicked.") 
     Cookies.remove('username') 
     Cookies.remove('first_name') 
     Cookies.remove('last_name') 
     Cookies.remove('email') 
     window.location.href = window.location.origin + '/logout' 
    } 
}) 

服務器:

/* GET home page. */ 
router.get('/', function(req, res, next) { 
    res.render('main') 
}); 

router.put('/login', function(req, res) { 
    // Password is not encrypted here 
    console.log('req.body') 
    console.log(req.body) 

    User.findOne({ username: req.body.username }, function(err, user) { 
     // Password is encrypted here 
     if (err) throw err 
     console.log('user') 
     console.log(user) 

     bcrypt.compare(req.body.password, user.password, function(err, result) { 
      if (result) { 
       var token = jwt.encode(user, JWT_SECRET) 
       // return res.status(200).send({ user: user, token: token }) 
       return res.redirect('/') 
      } else { 
       return res.status(401).send({error: "Something is wrong."}) 
      } 
     }) 
    }) 
}) 

我不能讓main.hbs一個成功登錄後呈現。我的評論代碼工作,但我試圖做我的重定向服務器端而不是客戶端,因爲我被告知,這對安全性更好。

+2

您的評論代碼是正確的工作方式。這裏沒有安全損失。您的重定向以任何方式傳達給用戶。服務器端重定向是爲ajax請求設計的,因爲該指令不是針對瀏覽器的,而是一些JavaScript處理程序。 –

+0

謝謝!這真的很好知道。我評論的代碼對我來說很有意義,我想要朝這個方向發展,但我擔心用戶的安全問題。如果我能夠在客戶端上使用JavaScript(在將請求提交給服務器之前),我將能夠進行自定義驗證,而不僅限於HTML5表單驗證。 – Farid

回答

1

我不認爲你想要做什麼是可能的。 AJAX請求只是爲了傳遞數據。現在發生的事情是,你需要在你的端腳本客戶端行爲腳本。這意味着AJAX請求會傳遞一個302和其他數據到JS上的回調。客戶端行爲不能從服務器上改變。這取決於你使用AJAX返回值做些什麼。如果500,拋出錯誤信息,200做某事等

您可以通過傳統的HTML表單提交來獲得服務器重定向的唯一方法。

+0

好吧,所以我認爲我在我的評論代碼中做了這些,我在客戶端用'window.location.href = window.location.origin +'/''做了重定向。對於登錄系統,使用傳統的HTML提交以便重定向發生在服務器端更好嗎? – Farid

+0

與所有事情一樣,這取決於。如果你正在做一個純粹的單頁面應用程序,那麼使用客戶端的東西。但是,從你的代碼判斷,你不是。在我看來,基本的服務器端重定向更適合這裏。 如果你登錄GMail或其他,他們也在做服務器端重定向。 希望這會有所幫助。 –

+0

是的,這有幫助。謝謝你的明確答案! – Farid

3

您應該知道何時使用hrefreplace功能。

window.location.replace(...)將代表HTTP重定向的最佳方式。

原因

相較於window.location.hrefwindow.location.replace(...)是更好的HTTP使用重定向的情形,因爲replace()避免保持原始頁面會話歷史記錄,這有助於用戶避免陷入永無止境後退按鈕失敗。

摘要

如果你想說明點擊鏈接,使用location.href

如果你想說明一個HTTP重定向,使用location.replace

樣品

// an HTTP redirect 
window.location.replace("http://example.com"); 

// clicking on a link 
window.location.href = "http://example.com"; 

更新

服務器無法從ajax請求進行重定向。最後,ajax涉及客戶端(瀏覽器)。

如果需要,您可以通過服務器端調用發送重定向指令,但在回調中它將在客戶端再次結束。 您可以通過從包含要重定向到的URL的服務器返回對象來實現此目的。然後使用javascript更改文檔的位置屬性。如下圖所示:

服務器端代碼

if (result) { 
    var token = jwt.encode(user, JWT_SECRET) 
    return res.status(200).send({result: 'redirect', url:'/'}) 
} else { 
    return res.status(401).send({error: "Something is wrong."}) 
} 

然後在客戶端的JavaScript:

$.ajax({ 
    type: "put", 
    url: '/login', 
    data: { 
    username: username, 
    password: password 
    } 
    success: function(response) { 
    if (response.result == 'redirect') { 
     //redirecting to main page from here. 
     window.location.replace(response.url); 
    } 

    } 
}); 
從此您的註釋代碼

除了是這樣做的正確方法。就像您在其中的一條評論一樣,「服務器端重定向是爲ajax請求設計的,因爲該指令不適用於瀏覽器,而是一些JavaScript處理程序。」

+0

感謝您的解釋!問題:安全性比其他方法更好嗎?根據你的解釋,我想'location.replace'是要走的路。 – Farid

+0

@Farid是的,這是正確的使用'location.replace'無論你想重定向 –

+0

@Farid如果答案是有用的和正確的,你可以把它標記爲正確的答案! –