Skip to content

单页面应用的重定向

场景描述

很多网站都会有登录校验,其流程如下:

  1. 访问网站网址;
  2. 服务器发现请求的请求头或者Cookie中没有带有登录信息(一般是一个Token),就返回一个状态码为302的重定向响应,并在响应头的Location中写入重定向的地址,从而跳转至登陆页面;
  3. 浏览器接收到响应后**(注:对于3xx的重定向响应,axios无法拦截,是浏览器自动处理的)**,发现是302,就会用 get 方法重新请求 Location 中指定的登录网址;
  4. 在登录网址输入账号密码登录后,服务端会在响应的 Set-Cookie 中写入我们的登录信息,同时浏览器的代码会重新跳转到我们一开始访问的页面。

问题这里我是一个单页面应用,一开始,我的观察一下当后端返回302时,浏览器这边显示状态码302,location就是对应的网址(无效的网址会进行拼接https://juejin.cn/post/6844904151705452552),如下

egg后端
ctx.redirect('/user/login')

浏览器接收到服务器响应为
Status Code: 302 Found
location: /user/login
然后会自动发起一个get请求
http://localhost:8000/user/login

出现问题1:发送了请求但页面没跳转到登录页啊?(初始页不是登录页)

原因:单页面应用的页面是靠history或者hash切换的,浏览器发起的请求并不会改变页面

🙄好吧,我想这问题也好解决,咱么写个axios拦截器,判断下这次返回是否是个302然后手动跳转不就行了,结果试了一下,da mei

问题2:发现axios根本拦截不到302,对于3xx的重定向都是由浏览器自动处理的(Axios 响应不能拦截 302 状态码?),这...

解决方式1 不使用302

与后端沟通(这里就是和我自己沟通😑)

遇到重定向,使用如401,手动设置location,然后前端拦截401根据location进行手动跳转

解决方式2 reponseUrl

限制:重定向后的页面要保证正常返回

不用找后端了,浏览器在遇到302后自动发起一个get请求,通过axios的response拦截器,发现res.request.responseUrl就是重定向的url,从而可以判断是否发生过重定向,然后手动跳转

json
{
    ...
    request:  {
        ...
    	responseURL: "http://localhost:8000/user/login"
    	...
	}	...
}

解决方式3 约定url参数

在302时约定在url上携带参数如_redirect_url,前端在进入页面是检查参数,判断是否发生重定向

解决方式4 fetch

redirect: 'manual':阻止 fetch 自动跟随重定向。

js
fetch('https://example.com/some-url', {
  redirect: 'manual' // 阻止 fetch 自动重定向
})
.then(response => {
  if (response.status === 302) {
    const location = response.headers.get('Location'); // 获取重定向目标
    console.log('重定向目标:', location);

    // 如果需要,可以手动跳转
    // window.location.href = location;
  } else {
    return response.json(); // 处理其他响应
  }
})
.then(data => {
  console.log('响应数据:', data);
})
.catch(error => {
  console.error('请求失败:', error);
});

苏ICP备2025160170号-1 | 前端进化之路 | Released under the MIT License.