最近解决基于.net mvc项目的session失效问题,这个跟大家聊聊。

1.问题分析

.net mvc中,Session失效需要考虑几种情况:

  • 基于权限认证的Action,使用非Ajax请求;
  • 基于权限认证的Action,使用JQueryt Ajax请求;
  • 基于权限认证的Action,使用.net mvc封装的Ajax请求;
  • 无权限认证的Action,使用非Aajx请求;
  • 无权限认证的Action,使用原生JQuery Ajax请求;
  • 无权限认证的Action,使用.net mvc封装的Ajax请求;

基于权限认证的Action,session失效后AuthorizeAttribute都可以拦截,并在HandleUnauthorizedRequest方法中处理;无权限认证的Action需要在自定义的filter中,根据新建Session与已请求Session的区别进行判断和处理。

2.基于权限认证的非Ajax请求

Authorize filter优先于其他功能过滤器执行,因此这里继承AuthorizeAttribue,在HandleUnauthorizedRequest中处理session请求。

public class AuthorizeOfHandleUnAuthorizeAttribute:AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//session失效重定向到登录页面
filterContext.Result =
new RedirectToRouteResult(
new RouteValueDictionary(new { Controller = "Login", Action = "Login" }));
}
}

3.基于权限认证的Ajax请求

Ajax请求的Action在系统中存在两种返回结果:JsonResult和PartialViewResult。

  • JsonResult理论上可以通过在返回的结果上增加session超期属性,客户端进行判断即可。但是考虑到项目已经完成,在所有ajax请求上增加判断逻辑有些繁琐。

服务端代码处理ajax请求:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//ajax请求session超期处理
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.AppendHeader("sessionstatus","timeout");
filterContext.HttpContext.Response.End();
return;
}
filterContext.Result =
new RedirectToRouteResult(
new RouteValueDictionary(new { Controller = "Login", Action = "Login" }));
}

客户端代码(这种处理方式对于返回结果为PartialViewResult的Action是不适用的):

onSuccess: function (xhr, status) {
//获取响应头,sessionstatus,
var sessionstatus = xhr.getResponseHeader("sessionstatus");
if (sessionstatus == "timeout") {
window.location = "/Login/Login";
}
}
  • PartialViewResult情况的存在,直接否定上面的设想。项目中大部分Ajax请求都是基于.net mvc封装的,直接更新指定div。

为了不做大量更改、且统一处理两种返回结果的ajax请求,找到了另外一种方法

jQuery.ajaxSetup()

该函数用于更改jQuery中AJAX请求的默认设置选项。之后执行的所有AJAX请求,如果对应的选项参数没有设置,将使用更改后的默认设置。

因此我们的客户端代码可以这样统一处理:

 //解析ajax请求session超时问题
$.ajaxSetup({
complete: function(xmlHttpRequest, textStatus) {
var sessionStatus = xmlHttpRequest.getResponseHeader("sessionstatus");
if (sessionStatus === "timeout") {
window.location = "/Login/Login";
}
}
});

本以为到这里就万事大吉啦,结果一不小心又发现一个问题,基于.net mvc的jquery.unobtrusive-ajax封装的ajax请求调用,没有达到拦截处理的效果。经过反复调试无果,最终还是注意到上面那段话

jQuery.ajaxSetup()该函数用于更改jQuery中AJAX请求的默认设置选项。之后执行的所有AJAX请求,如果对应的选项参数没有设置,将使用更改后的默认设置

这里说的比较明白了,那肯定就是jquery.unobtrusive-ajax封装的时候捣的鬼啦,翻开源码一看果然如此:

    $.extend(options, {
type: element.getAttribute("data-ajax-method") || undefined,
url: element.getAttribute("data-ajax-url") || undefined,
cache: !!element.getAttribute("data-ajax-cache"),
beforeSend: function (xhr) {
var result;
asyncOnBeforeSend(xhr, method);
result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments);
if (result !== false) {
loading.show(duration);
}
return result;
},
complete: function (xhr,status) {
loading.hide(duration);
getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments);
},
success: function (data, status, xhr) {
asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments);
},
error: function () {
getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments);
}
});

我们看到jquery.unobtrusive-ajax注册了ajax请求的compelete事件,因此我们写的默认处理程序就被覆盖啦。实在没想到什么好办法,只好改下jquery.unobtrusive-ajax的源码了:

complete: function (xhr,status) {

loading.hide(duration);

            //解析ajax请求session超时问题
var sessionStatus = xhr.getResponseHeader("sessionstatus");
if (sessionStatus === "timeout") {
window.location = "/Login/Login";
} getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments);
},

至此,基于认证的ajax请求session失效问题基本解决,存在两个瑕疵:

  • 修改了jquery.unobtrusive-ajax的源码,总感觉心里别扭;
  • 任何注册了compelete事件的ajax请求,都需要自己处理session问题。

4.无权限任务的Action

无权限认证的Action的Session失效问题,处理代码如下:

if (filterContext.HttpContext.Session != null)
{
if (filterContext.HttpContext.Session.IsNewSession)
{
var sessionCookie = filterContext.HttpContext.Request.Headers["Cookie"];
if (sessionCookie != null&&sessionCookie.IndexOf("ASP_NET_SessionId",StringComparison.OrdinalIgnoreCase)>=0)
{
filterContext.Result =
new RedirectToRouteResult(
new RouteValueDictionary(new { Controller = "Login", Action = "Login" })); }
}
}

无权限认证的Action的Ajax可以仿照上面有权限认证的处理方法处理,这里就不再粘代码啦。个人感觉,无权限认证的Action请求,大多可以不用考虑session失效情况,因为这些Action大多不从session里获取信息,只是做公共信息的查询。

5.遗留问题

至此问题基本解决,但是过程中遇到了一个莫名其妙的问题,暂且记下:

我原本通过在配置文件把session超期时间设置的很小来模拟session失效,结果发现项目现有框架总会莫名奇妙的在登录后的第一个业务请请求时把session超期时间改为60分钟,没有找到为什么。后来只能通过在同一个浏览器打开两个tab页,登录系统后,在一个tab页推出的方法模拟。

以上是我解决项目中问题的过程,里面如果有认识的偏颇,还望园友指出。在问题的解决过程中,参考以下几篇问题,在此列出并表示感谢:

.net mvc session失效问题的更多相关文章

  1. [转]菜鸟程序员之Asp.net MVC Session过期异常的处理

    本文转自:http://www.cnblogs.com/JustRun1983/p/3377652.html 小赵是刚毕业的计算机专业方面的大学生,4年的大学时间里面,他读过了很多编程方面的数据,也动 ...

  2. 菜鸟程序员之Asp.net MVC Session过期异常的处理

    小赵是刚毕业的计算机专业方面的大学生,4年的大学时间里面,他读过了很多编程方面的数据,也动手也了很多代码.现在毕业了,他如愿的加入了T公司,开始了自己的程序员生涯.他信心满满,相信自己4年的学习到的东 ...

  3. Asp.net MVC Session过期异常的处理

    一.使用MVC中的Filter来对Session进行验证 (1)方法1: public class MyAuthorizeAttribute : FilterAttribute, IAuthoriza ...

  4. 详解springmvc控制登录用户session失效后跳转登录页面

    springmvc控制登录用户session失效后跳转登录页面,废话不多少了,具体如下: 第一步,配置 web.xml <session-config> <session-timeo ...

  5. 让Session失效的三种方法

    我们设置SESSION失效的时间,是为了确保在用户长时间不与服务器交互的情况下,可以自动退出登录.本文介绍了三种设置SESSION失效的方法,希望对你有帮助. Session对象是HttpSessio ...

  6. 第三方支付过程中session失效问题

    第三方支付过程中session失效问题 时间 2015-05-13 12:36:23  IT社区推荐资讯 原文  http://itindex.net/detail/53436-session-问题 ...

  7. ASP.Net中Session失效的一种编程思路

    在写一个客户的B/S结构应用程序时,突然发现一个技巧,不知道是否是MS的一个BUG,给相关的有研究的朋友原先考虑写一个检查Session的类,Session失效后,必须转向登陆页面,可每一个调用该类的 ...

  8. session失效后跳转到登陆页面

    一.编写Filter拦截器类 package com.pv.utils; import java.io.IOException; import java.io.PrintWriter; import ...

  9. 设置session失效的几种方法

    转自:http://www.cnblogs.com/linjiqin/archive/2011/06/15/2081673.html 在系统登录后,都会设置一个当前session失效的时间,以确保在用 ...

随机推荐

  1. JQuery实现 图片上传

    用到的文件,我都已经打包好了,自行下载: https://files.cnblogs.com/files/lguow/lib.rar 核心代码如下: <input type="hidd ...

  2. HttpSession的API

    //获取Session对象request.getSession()request.getSession(boolean create)//获取SessionIdgetId()//获取当前session ...

  3. [Swift]LeetCode171. Excel表列序号 | Excel Sheet Column Number

    Given a column title as appear in an Excel sheet, return its corresponding column number. For exampl ...

  4. [Swift]LeetCode314. 二叉树的竖直遍历 $ Binary Tree Vertical Order Traversal

    Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bott ...

  5. [Swift]LeetCode374. 猜数字大小 | Guess Number Higher or Lower

    We are playing the Guess Game. The game is as follows: I pick a number from 1 to n. You have to gues ...

  6. [Swift]LeetCode518. 零钱兑换 II | Coin Change 2

    You are given coins of different denominations and a total amount of money. Write a function to comp ...

  7. [Swift]LeetCode874. 模拟行走机器人 | Walking Robot Simulation

    A robot on an infinite grid starts at point (0, 0) and faces north.  The robot can receive one of th ...

  8. 【Maven】---Nexus私服配置Setting和Pom

    maven---nexus私服配置setting和pom 上一遍博客已经在linux服务器上,搭建好nexus私服了,博客地址:Linux搭建Nexus3.X私服 现在就需要配置setting.xml ...

  9. RabbitMQ学习笔记(五) Topic

    更多的问题 Direct Exchange帮助我们解决了分类发布与订阅消息的问题,但是Direct Exchange的问题是,它所使用的routingKey是一个简单字符串,这决定了它只能按照一个条件 ...

  10. 浅谈新的布局方式-flex

    引言: 网页布局在flex出来之前,是由盒模型为底子,float,position,table,百分比来进行布局的,重绘的比较多,影响性能,复杂又不好维护.flex布局,可以简便.完整.响应式地实现各 ...