最近解决基于.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. kali linux 网络渗透测试学习笔记(二)OWASP ZAP工具扫描SQL injection漏洞失败

    按照惯例,利用OWASP ZAP工具扫描SQL injection漏洞时,应该很快就可以扫描出来,但是在笔者进行扫描的时候,却遇到了以下状况: 这说明了该工具根本就没能够扫描出SQL注入的漏洞,不知道 ...

  2. 图片转web字体库,如何制作web字体库

    最近项目上用到了很多svg图,设计师经常频繁改版,苦不堪言,于是就想到了把图片转成字体库来使用. 使用图片的缺点: 1. 图片加载速度慢 2. 图片大小固定,无法调节 3. 当代码重构或者图片目录位置 ...

  3. 最新手机号正则表达式 java 、javascript版正则表达式验证是否为11位有效手机号码

    最近在做注册登陆页面,都要涉及到验证11位有效手机号码,这里贴出代码,希望能帮到有这个开发需求的朋友. function isPoneAvailable($poneInput) { var myreg ...

  4. mysql tablespace(独立表空间)超速备份大数据

    前序 对于用户自主创建的表,会采用此种模式,每个表由一个独立的表空间进行管理备份(速度相当的猛) 首先介绍一下文件 .ibd就被称之为独立表空间的数据文件 .frm就是元数据文件 就是创建表后生成的 ...

  5. pytthon—day8 读写模式的结合、文件操作模式、with完成文本文件复制、游标操作

    一.读写模式的结合 w:写指没有新建文件,有文件就清空 w=open('1.txt','w',encoding='utf-8') w.write('000\n') 在写入数据时,需要及时处理内存空间, ...

  6. Python内置函数(32)——input

    英文文档: input([prompt]) If the prompt argument is present, it is written to standard output without a ...

  7. JVM基础系列第7讲:JVM 类加载机制

    当 Java 虚拟机将 Java 源码编译为字节码之后,虚拟机便可以将字节码读取进内存,从而进行解析.运行等整个过程,这个过程我们叫:Java 虚拟机的类加载机制.JVM 虚拟机执行 class 字节 ...

  8. MacPro4,1升级到MacPro5,1

    收了一台老MacPro,2009年版本,准确型号是"MacPro4,1".机器很好,美中不足的是,太老了.硬件还好说,很多部件都可以单独采购升级,特别是有了淘宝,几乎只要有的东西, ...

  9. Android Studio代码行数统计插件Statistics

    Android Studio 是没有提提供统计代码全部行数的功能的,但是对于开发者来说,这个功能确实必备的,Statistic统计代码行数非常方便,也很详细. 1,首先肯定是将插件下载下来,下载地址: ...

  10. SpringBoot入门教程(十七)@Service、@Controller、@Repository、@Component

    spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository.@Service 和 @Controller.在目前的 Spring ...