单页面应用的重定向
场景描述
很多网站都会有登录校验,其流程如下:
- 访问网站网址;
- 服务器发现请求的请求头或者
Cookie
中没有带有登录信息(一般是一个Token
),就返回一个状态码为302
的重定向响应,并在响应头的Location
中写入重定向的地址,从而跳转至登陆页面; - 浏览器接收到响应后**(注:对于3xx的重定向响应,axios无法拦截,是浏览器自动处理的)**,发现是302,就会用
get
方法重新请求 Location 中指定的登录网址; - 在登录网址输入账号密码登录后,服务端会在响应的
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);
});