.net mvc session失效问题
最近解决基于.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页推出的方法模拟。
以上是我解决项目中问题的过程,里面如果有认识的偏颇,还望园友指出。在问题的解决过程中,参考以下几篇问题,在此列出并表示感谢:
- http://www.cnblogs.com/JustRun1983/p/3377652.html
- http://blog.csdn.net/yeyicsdn/article/details/50032787
.net mvc session失效问题的更多相关文章
- [转]菜鸟程序员之Asp.net MVC Session过期异常的处理
本文转自:http://www.cnblogs.com/JustRun1983/p/3377652.html 小赵是刚毕业的计算机专业方面的大学生,4年的大学时间里面,他读过了很多编程方面的数据,也动 ...
- 菜鸟程序员之Asp.net MVC Session过期异常的处理
小赵是刚毕业的计算机专业方面的大学生,4年的大学时间里面,他读过了很多编程方面的数据,也动手也了很多代码.现在毕业了,他如愿的加入了T公司,开始了自己的程序员生涯.他信心满满,相信自己4年的学习到的东 ...
- Asp.net MVC Session过期异常的处理
一.使用MVC中的Filter来对Session进行验证 (1)方法1: public class MyAuthorizeAttribute : FilterAttribute, IAuthoriza ...
- 详解springmvc控制登录用户session失效后跳转登录页面
springmvc控制登录用户session失效后跳转登录页面,废话不多少了,具体如下: 第一步,配置 web.xml <session-config> <session-timeo ...
- 让Session失效的三种方法
我们设置SESSION失效的时间,是为了确保在用户长时间不与服务器交互的情况下,可以自动退出登录.本文介绍了三种设置SESSION失效的方法,希望对你有帮助. Session对象是HttpSessio ...
- 第三方支付过程中session失效问题
第三方支付过程中session失效问题 时间 2015-05-13 12:36:23 IT社区推荐资讯 原文 http://itindex.net/detail/53436-session-问题 ...
- ASP.Net中Session失效的一种编程思路
在写一个客户的B/S结构应用程序时,突然发现一个技巧,不知道是否是MS的一个BUG,给相关的有研究的朋友原先考虑写一个检查Session的类,Session失效后,必须转向登陆页面,可每一个调用该类的 ...
- session失效后跳转到登陆页面
一.编写Filter拦截器类 package com.pv.utils; import java.io.IOException; import java.io.PrintWriter; import ...
- 设置session失效的几种方法
转自:http://www.cnblogs.com/linjiqin/archive/2011/06/15/2081673.html 在系统登录后,都会设置一个当前session失效的时间,以确保在用 ...
随机推荐
- MySQL 分区建索引
200 ? "200px" : this.width)!important;} --> 介绍 mysql分区后每个分区成了独立的文件,虽然从逻辑上还是一张表其实已经分成了多张 ...
- 【RL-TCPnet网络教程】第31章 Telnet远程登录基础知识
第31章 Telnet远程登录基础知识 本章节为大家讲解Telnet (Teletype Network) 的基础知识,方便后面章节的实战操作. (本章的知识点主要整理自网络) 31.1 ...
- [Swift]LeetCode168. Excel表列名称 | Excel Sheet Column Title
Given a positive integer, return its corresponding column title as appear in an Excel sheet. For exa ...
- [Swift]LeetCode313. 超级丑数 | Super Ugly Number
Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...
- [Swift]LeetCode777. 在LR字符串中交换相邻字符 | Swap Adjacent in LR String
In a string composed of 'L', 'R', and 'X'characters, like "RXXLRXRXL", a move consists of ...
- [Swift]LeetCode903. DI 序列的有效排列 | Valid Permutations for DI Sequence
We are given S, a length n string of characters from the set {'D', 'I'}. (These letters stand for &q ...
- [Swift]LeetCode942. 增减字符串匹配 | DI String Match
Given a string S that only contains "I" (increase) or "D" (decrease), let N = S. ...
- 浅谈React
浅谈react react是什么?其官网给出了明确定义:A JavaScript library for building user interfaces,一个用于构建用户界面的JavaScript库 ...
- Cassandra事务与关系型数据库事务有何区别
Cassandra不会使用回滚和锁机制来实现关系型数据的ACID事务,相比较于提供原子性,隔离性和持久化,Cassandra提供最终(可调节的)一致性,让用户决定为每个事务提供强一致性或者最终一致性. ...
- 谷歌浏览器的各种插件网址Chrome插件(谷歌浏览器)-超级详细
各种各样的插件,可以查找对自己有用的,自行下载安装 http://chromecj.com/