拦截Response.Redirect的跳转并转换为Js的跳转

本文详细介绍了如何通过自定义的AjaxHttpModule拦截Response.Redirect,将跳转链接转换为JSON字符串,以便Ajax请求能够正确处理登录检查,避免直接跳转导致的用户体验不佳。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有一个很常见的需求,某个页面需要用户登录才能访问,或者某个操作需要用户登录

这就需要检测用户登录,一般是使用Ajax去检测是否登录,当用户未登录时跳转到登录页面

那么问题来了····

有的时候我们跳转到登录是直接Redirect,而有的时候因为是使用的Ajax,所以直接必须在客户端用Js使用location.href进行跳转

网上找了好久···找不到,然后想起Ext.Net实现了这个需求

就直接参考了Ext.Net的实现,也就是根据需求拦截Response.Redirect的跳转并转换为location.href

直接上代码

 1 public class AjaxHttpModule : IHttpModule
 2     {
 3         public void Dispose()
 4         {
 5             throw new NotImplementedException();
 6         }
 7 
 8         public void Init(HttpApplication context)
 9         {
10             context.PreSendRequestHeaders += context_PreSendRequestHeaders;
11         }
12 
13         void context_PreSendRequestHeaders(object sender, EventArgs e)
14         {
15             HttpApplication application = sender as HttpApplication;
16             HttpContext context = application.Context;
17             if ((context.Response.StatusCode == 0x12e) && (context.Request.Headers.AllKeys.Contains("X-Requested-With")))
18             {
19                 string redirectLocation = context.Response.RedirectLocation;
20                 context.Response.ClearContent();
21                 context.Response.StatusCode = 200;
22                 context.Response.ContentType = "text/html";
23                 context.Response.Charset = "utf-8";
24                 context.Response.Headers.Remove("location");
25                 context.Response.Output.Write("{\"script\":\"window.location.href='" + redirectLocation + "';\"}");
26             }
27         }
28     }

代码很简单,当检测到响应到状态码为302并且是一个Ajax请求时,则自定义响应内容

将跳转的地址拼接为一个json字符串由客户端解析,最终解析结果为

{script:"window.location.href='/game/Play';"}

转载于:https://www.cnblogs.com/wzxinchen/p/4309744.html

<think>我们是在前端项目中,通常会在request.js(或类似名称,如axios.js)中封装全局的HTTP请求拦截器。用户的需求是:在请求拦截器中,当遇到特定情况(如认证失败、session过期)时,如何跳转到指定路由页面(如登录页)。注意:request.js是纯JavaScript模块,通常不直接包含路由功能。因此,我们需要将路由对象或路由跳转方法注入到请求拦截器中。根据引用[2]和引用[4][5]提供的信息,我们可以总结出两种主要方式:1.拦截器中使用ReactRouter或VueRouter提供的API进行跳转(需要先获取路由对象)2.通过返回一个特定的状态(如重定向指令),然后在组件中处理跳转(如使用<Redirect>组件)然而,在请求拦截器(一个独立的js模块)中,我们通常无法直接使用路由组件的API,因为这里没有组件上下文。所以我们需要采用一些间接的方法。下面分别针对React和Vue给出解决方案:###React项目(使用ReactRouter)在React中,我们可以在请求拦截器中通过以下方式实现路由跳转:**方法一:使用history对象(推荐)**1.在项目入口文件(如App.js)中创建一个history对象(可以使用`history`包创建),然后将这个history对象传递给拦截器模块。2.拦截器中使用history对象进行跳转。步骤:-安装history包:`npminstallhistory`-创建history对象导出(可以在一个单独的文件中,例如`history.js`):```javascriptimport{createBrowserHistory}from'history';exportdefaultcreateBrowserHistory();```-在请求拦截器文件中引入这个history对象,然后使用它跳转:```javascriptimporthistoryfrom'./history';//在响应拦截器中axios.interceptors.response.use(response=>response,error=>{if(error.response.status===401){//未认证,跳转到登录页history.push('/login');}returnPromise.reject(error);});```**方法二:使用ReactRouter的withRouter高阶组件(不适用于拦截器)**这种方法通常用于组件内部,在拦截器中无法使用。**方法三:使用Context(不常用)**可以将路由的history对象通过Context传递给非组件模块,但实现起来较复杂。###Vue项目(使用VueRouter)在Vue中,我们可以直接在拦截器中使用路由实例,因为VueRouter的路由实例可以通过`import`引入。步骤:1.在定义路由的文件中(如`router/index.js`)导出路由实例。2.请求拦截器文件中导入路由实例,然后使用`router.push`方法跳转。示例代码:在`router/index.js`中:```javascriptimportVuefrom'vue';importRouterfrom'vue-router';importLoginfrom'@/views/Login.vue';Vue.use(Router);constrouter=newRouter({routes:[//...路由配置]});exportdefaultrouter;//导出路由实例```在`request.js`(或`axios.js`)中:```javascriptimportrouterfrom'@/router';//导入路由实例//创建axios实例constservice=axios.create({//...配置});//响应拦截器service.interceptors.response.use(response=>{returnresponse;},error=>{if(error.response.status===401){//跳转到登录页router.push('/login');}returnPromise.reject(error);});exportdefaultservice;```###注意事项:1.**避免在拦截器中直接使用`window.location`**:虽然这样可以跳转,但会导致整个页面刷新,不符合SPA的无刷新跳转原则。2.**处理异步问题**:确保在跳转前完成必要的清理工作(如清除用户token等)。3.**避免循环跳转**:比如在登录页也可能会触发401,所以要确保登录页的请求不会触发拦截器的跳转,否则会陷入死循环。###示例:处理401未授权跳转到登录页以下是一个Vue项目中axios拦截器的完整示例:```javascriptimportaxiosfrom'axios';importrouterfrom'./router';importstorefrom'./store';//如果有vuexstore//创建axios实例constservice=axios.create({baseURL:process.env.VUE_APP_BASE_API,timeout:5000});//请求拦截器service.interceptors.request.use(config=>{//在请求头中添加tokenif(store.getters.token){config.headers['Authorization']=`Bearer${store.getters.token}`;}returnconfig;},error=>{returnPromise.reject(error);});//响应拦截器service.interceptors.response.use(response=>{constres=response.data;//假设业务状态码20000为成功if(res.code!==20000){//业务错误处理returnPromise.reject(newError(res.message||'Error'));}else{returnres;}},error=>{if(error.response){switch(error.response.status){case401://清除用户token等store.dispatch('user/resetToken');//跳转到登录页,携带当前页面路径,以便登录后回跳router.push(`/login?redirect=${router.currentRoute.fullPath}`);break;case403://无权限break;default:console.log('其他错误');}}returnPromise.reject(error);});exportdefaultservice;```###相关问题1.如何在拦截器中处理多个不同的错误状态码?2.在React项目中,如何避免在拦截器中直接使用`history.push`导致组件不更新的问题?3.如何实现登录后重定向回原请求页面的功能?4.在Vue项目中,如何避免在拦截器中使用`router.push`时重复跳转?5.如何在请求拦截器中实现取消重复请求的功能?以上方法在React和Vue中都是可行的,根据具体项目使用的框架和路由库选择适合的方式。</think>在前端项目中,通常会在 `request.js` 文件(或类似名称的请求封装文件)中处理全局请求拦截。以下是针对 React 和 Vue 框架实现路由跳转的解决方案: --- ### **React 项目解决方案** #### 核心思路:使用 `history` 对象进行跳转 1. **创建独立 history 对象** ```javascript // src/history.js import { createBrowserHistory } from 'history'; export default createBrowserHistory(); ``` 2. **在请求拦截器中使用** ```javascript // src/utils/request.js import history from './history'; import axios from 'axios'; const service = axios.create(); service.interceptors.response.use( response => response, error => { if (error.response.status === 401) { // Session 过期 history.push('/login?redirect=' + encodeURIComponent(window.location.pathname)); } return Promise.reject(error); } ); ``` 3. **在入口文件注入路由** ```javascript // src/index.js import { Router } from 'react-router-dom'; import history from './history'; import App from './App'; ReactDOM.render( <Router history={history}> <App /> </Router>, document.getElementById('root') ); ``` --- ### **Vue 项目解决方案** #### 核心思路:直接使用 Vue Router 实例 1. **在请求文件中引入 router** ```javascript // src/utils/request.js import axios from 'axios'; import router from '@/router'; // 导入路由实例 const service = axios.create(); service.interceptors.response.use( response => response, error => { if (error.response.status === 403) { // 无权限 router.push({ path: '/login', query: { redirect: router.currentRoute.fullPath } }); } return Promise.reject(error); } ); ``` --- ### **通用技巧(React/Vue 均适用)** #### 1. 重定向到来源页面 ```javascript // 跳转时携带当前路径 const redirect = encodeURIComponent(window.location.pathname + window.location.search); history.push(`/login?redirect=${redirect}`); // React router.push(`/login?redirect=${redirect}`); // Vue ``` #### 2. 登录后处理重定向 ```javascript // 登录组件中 const query = new URLSearchParams(location.search); // React const redirect = query.get('redirect') || '/home'; // Vue 可直接使用 this.$route.query.redirect ``` #### 3. 路由守卫结合方案 ```javascript // Vue 路由守卫示例 (src/router/index.js) router.beforeEach((to, from, next) => { if (to.meta.requiresAuth && !hasToken()) { next(`/login?redirect=${to.path}`); } else { next(); } }); ``` --- ### **注意事项** 1. **避免循环跳转** ```javascript // 排除登录页本身 if (error.response.status === 401 && !window.location.pathname.includes('/login')) { // 执行跳转 } ``` 2. **服务端响应规范** 确保 API 返回明确的错误状态码: - `401 Unauthorized`:身份认证失败 - `403 Forbidden`:权限不足 3. **状态管理整合** 跳转前清理用户状态(Vuex/Redux): ```javascript // 在跳转前清理用户数据 store.dispatch('user/resetUser'); // Vuex dispatch({ type: 'LOGOUT' }); // Redux ``` --- ### **示例项目结构** ``` src/ ├── utils/ │ ├── request.js # 请求拦截器 │ └── history.js # (React专用) ├── router/ # 路由配置 ├── store/ # 状态管理 └── views/ ├── Login.vue # 登录页 └── ... ``` > **最佳实践**:在请求拦截器中处理通用认证逻辑,在路由守卫中处理页面级权限控制,两者结合使用[^2][^4]。 --- ### **相关问题** 1. 如何在 Axios 拦截器中实现自动刷新 Token? 2. 前端路由守卫如何处理动态权限? 3. 如何防止未认证用户直接访问受限路由? 4. 在微前端架构中如何处理全局认证跳转? 5. 如何实现无感刷新 Token 的机制? [^1]: 路由重定向的基本配置示例 [^2]: React 中配合 axios 实现拦截跳转 [^4]: 使用路由守卫进行认证控制 [^5]: React 中通过状态控制路由跳转
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值