来自 AJAX 调用的 res.redirect

Posted

技术标签:

【中文标题】来自 AJAX 调用的 res.redirect【英文标题】:res.redirect from an AJAX call 【发布时间】:2017-10-13 17:53:47 【问题描述】:

我正在尝试在 ajax put 请求之后进行重定向。我打算使用纯 JS 客户端进行验证。

客户:

$(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 呈现。我的注释代码有效,但我正在尝试做我的重定向服务器端而不是客户端,因为我被告知它对安全性更好。

【问题讨论】:

您的注释代码是正确的工作方式。这里没有安全性损失。无论哪种方式,您的重定向都会传达给用户。服务器端重定向对于 ajax 请求是死路一条,因为该指令不是针对浏览器的,而是针对一些 javascript 处理程序的。 谢谢!这真是太好了。我的注释代码对我来说很有意义,我想朝那个方向发展,但我担心用户的安全性。如果我能够在客户端使用 JavaScript(在向服务器提交请求之前),我将能够进行自定义验证,而不是仅限于 html5 表单验证。 【参考方案1】:

您应该知道何时使用hrefreplace 功能。

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

原因

window.location.href 相比,window.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);
    

  
);

除此之外,您的注释代码是执行此操作的正确方法。就像您提出的问题中的一个 cmets 一样,“服务器端重定向对于 ajax 请求是死路一条,因为该指令不是针对浏览器的,而是针对一些 javascript 处理程序的。”

【讨论】:

感谢您的解释!问题:在安全性方面,一种方法比另一种更好吗?根据你的解释,我猜location.replace 是要走的路。 @Farid 是的,在你想要重定向的地方使用location.replace @Farid 如果答案有用且正确,您可以将其标记为正确答案! 安全性怎么样? location.replace 是一种安全的使用方法吗? 这不是切线吗?他要求服务器端重定向他的页面,而不是客户端代码。你说的是对的,但他的服务器端代码不允许更改窗口位置,不是吗?【参考方案2】:

我认为你想做的事情是不可能的。 AJAX 请求只是为了来回传递数据。现在发生的情况是,您需要在终端上编写客户端行为脚本。这意味着 AJAX 请求将传递一个 302 和其他随乘车而来的数据到 JS 上的回调。不能从服务器更改任何客户端行为。您可以对 AJAX 返回的值做一些事情。如果 500,则抛出错误消息,200 做某事等。

使服务器重定向工作的唯一方法是通过传统的 HTML 表单提交。

【讨论】:

好的,所以我想我是在我的注释代码中做到了这一点,我在客户端使用window.location.href = window.location.origin + '/' 进行了重定向。对于登录系统,是否最好只使用传统的 HTML 提交以便重定向发生在服务器端? 与所有事情一样,这取决于。如果您正在做一个纯单页应用程序,那么使用客户端的东西。但是,从您的代码来看,您不是。在我看来,基本的服务器端重定向更适合这里。如果您登录到 GMail 或其他什么,他们也会进行服务器端重定向。希望这会有所帮助。 我想问的其他问题:为了进行服务器端重定向,如您所述,我想我需要绕过客户端 JS(这是我上面的代码目前的工作方式) .如果我想在客户端使用 JS 进行自定义验证(超出 HTML5 表单验证可用的功能),这可能吗? 为什么不呢?您始终可以将一个或多个表单提交侦听器附加到您想要的控件,并在 JS 中做任何可能的事情。

以上是关于来自 AJAX 调用的 res.redirect的主要内容,如果未能解决你的问题,请参考以下文章

API 调用与来自前端的直接页面调用(AJAX)

来自 django 模板的 Ajax 调用

在字段上显示来自 AJAX 调用的验证错误

来自 AJAX 调用的 res.redirect

php 忽略来自ajax调用的粘性帖子

来自 .ajax() 调用的数据的 jQuery .find() 返回未定义