前言当我们访问某个网站的时候需要检测用户是否已经登录(通过Session是否为null),我们知道在WebForm中可以定义一个BasePage类让他继承System.Web.UI.Page,重写它的OnInit()方法,在OnInit()中判断Session中是否有用户登录的信息。

/// <summary>
/// 公共基类里面干一些公共的事情
/// </summary>
public class BasePage : System.Web.UI.Page
{
//页面生命周期Init事件对应的OnInit()方法
//这个方法会先于PageLoad方法执行
//override 表示重写 OnInit方法 OnInit 方法,在所有控件都已初始化且已应用所有外观设置后引发。使用该事件来读取或初始化控件属性
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (Session["UserInfo"] == null) //检查用户是否登录
{
//跳转到登录页面
}
}
}

 在mvc下该怎样校验呢?

我们知道,MVC下可以自定义特性类为控制器或控制器中的Action打上[特性],这里只需要ActionFilter过滤器(Action方法执行前后执行),MVC提供了IActionFilter接口。(为了方便我们可以用微软提供好的ActionFilterAttribute类,他是筛选器特性的基类,也是一个抽象类,其实这个抽象类实现了IActionFilter和IResultFilter)

IActionFilter接口的定义:

   //在执行操作方法后调用。
void OnActionExecuted(ActionExecutedContext filterContext); // 在执行操作方法之前调用。
void OnActionExecuting(ActionExecutingContext filterContext);

新建一个特性类LoginCheckFilterAttribute,让他继承ActionFilterAttribute,并重写其中的OnActionExecuting方法,在其中完成校验

public class LoginCheckFilterAttribute : ActionFilterAttribute
{
//表示是否检查登录
public bool IsCheck { get; set; } //Action方法执行之前执行此方法
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext); if (IsCheck)
{
//校验用户是否已经登录
if (filterContext.HttpContext.Session["loginUser"] == null)
{
//跳转到登陆页
filterContext.HttpContext.Response.Redirect("/UserLogin/Index");
}
}
}
}

怎么让这个过滤器起作用呢?

步骤:1、在Global.asax文件中为MVC程序注册全局过滤器, 调用FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)。FilterConfig类在App_Start文件夹中(创建新的MVC项目会自动生成),在FilterConfig的静态方法中public static void RegisterGlobalFilters(GlobalFilterCollection filters)注册全局过滤器

public class FilterConfig
{
//这个方法是用于注册全局过滤器(在Global中被调用)
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute());
filters.Add(new LoginCheckFilterAttribute() { IsCheck = true });
}
}

注意要为特性类实例的IsCheck属性赋值true否则Session校验不起作用。

这样子,LoginCheckFilterAttribute这个特性就会对整个MVC程序中的控制器和Action起作用了,就是说在执行Action方法之前会先调用特性类中的重写OnActionExecuting方法,这样用户在访问网站的时候会首先检测用户是否已经登录,如果没有登录会跳转到登录页面。

但是!但是!问题来了,因为我们注册的是全局的过滤器,这个过滤特性会对所有的控制器下的Action起作用,当访问网站的时候会(比如我们注册默认路由为/Home/Index)会首先跳转到/Home/Index,这时不会执行Index方法,会先执行OnActionExecuting()中的校验,发现Session为null,Response.Redirect("/UserLogin/Index")跳转到了登录页面;这时我们在浏览器中依然看不到登录页面,为什么呢?还记得我们注册的全局的过滤器,作用对象包括所有控制器下的Action当然也包括/UserLogin/Index,代码走到了这里会再次执行OnActionExecuting()方法,发现Session["UserInfo"==]null,又跳到了登录页面,我们连登录页面都见不着肯定不能输入用户名密码Session也就不会有登录信息,浏览器会返回 ”此网页包含重定向循环“ 的错误页面,也就是说会一直循环不停的重定向到登录页面,类似死循环,浏览器当然罢工了。。

该怎样解决这个bug的?

解决方法:为UserLoginController控制器打上特性

[LoginCheckFilterAttribute(IsCheck = false)]  //打上用户登录校验特性(IsCheck设为false不让它对此控制器起作用,而对其他控制器和Action起作用,防止重定向循环)
public class UserLoginController : Controller
{     ... }

我们在定义这个特性类的时候 有个bool属性 IsCheck,它表示是否校验,这里设为false表示不校验。顺便说一下LoginCheckFilterAttribute可以省略Attrbute后缀。

一定要在控制器上打这个特性,不要只针对下边的某个Action,因为这里边有生成验证码的Action和处理登录请求的Action,它们都不需要进行session校验(没意义),在控制器上打上特性会对它下边的所有Action起作用,不用为每个Action打特性了,节省代码量。我们注册了全局过滤器,又单独为UserLoginController控制器打上过滤特性,这里有一个优先级的问题Action>Controller>全局,UserLoginController不会受全局过滤器的影响。到这里测试一下,输入网站地址,成功进入登录页面。问题解决。

本文主要参考了:http://www.cnblogs.com/Look_Sun/p/4425083.html这篇文章。我遇到这个问题的时候,看了这篇文章和我开发时候遇到的问题基本一样。但是那哥们写的全局过滤器好像有问题,只需要判断Session["userinfo"]==null的时候就可以,他把Session["userinfo"]!=null的时候也做了判断,并做了跳转到。所有当点击登陆的时候,重定向到了/Home/Index,但是到了Home又会是个死循环。

MVC中过滤器中非常好的一个视屏:http://pan.baidu.com/s/1i5zwhjZ   回复我要密码  以后共同探讨问题

MVC中使用Action全局过滤器出现:网页无法正常运作 将您重定向的次数过多。解决办法的更多相关文章

  1. iOS 全局禁止横屏,但UIWebView 全屏播放视频,横屏,解决办法(任意页面横竖屏或禁止)

    iOS 全局禁止横屏,但UIWebView 全屏播放视频,横屏,解决办法 时间 2015-07-14 20:59:00  博客园-原创精华区 原文  http://www.cnblogs.com/fe ...

  2. SecureCRT SSH Linux中不显示彩色 字体颜色、文件夹和文件显示的颜色区别开解决办法

    SecureCRT SSH Linux中不显示彩色 字体颜色.文件夹和文件显示的颜色区别开解决办法 实验环境: 刚开始我的情况是这样的:带颜色的显示不出来,然后还能看到,此处有内容,猜测是Secure ...

  3. MVC下用户登录状态校验的问题以及解决方案--------------Action全局过滤器的使用

    前言当我们访问某个网站的时候需要检测用户是否已经登录(通过Session是否为null),我们知道在WebForm中可以定义一个BasePage类让他继承System.Web.UI.Page,重写它的 ...

  4. (原创)spring mvc和jersey rest 组合使用时单例对像实例化两次的BUG及解决办法

    项目中没用spring 的restTemplate 而是采用 jersey来做rest 的实现,一直用着,也没发现有什么不对,后来加入了,以quartz用硬编码方式实现,结果启动项目的时候报错 ,具体 ...

  5. 【Azure Developer】Github Action部署资源(ARM模板)到Azure中国区时,遇见登录问题的解决办法

    问题描述 在参考文档"使用 GitHub Actions 部署 ARM 模板"一文中,由于是在中国区Azure上操作,所以生产的部署凭证为中国区凭证.当创建工作流时,在登录到Azu ...

  6. 在WIn32程序中使用MFC的CInternetSession运行异常,主要是因为获取目前应用程序名出错的解决办法

    转载:http://group.gimoo.net/review/22564 头文件#include <afxinet.h"> 在非MFC工程中使用CInternetSessio ...

  7. Android中 在显示ImageView时图片上面和下面都出现一段空白区间的解决办法

    开始的时候是在ScrollView中显示ImageView的时候出现这样的问题,以为是要对ScrollView进行设置的,后来发现单独显示一个ImageView的时候也会出现这样的问题,由此才知道是应 ...

  8. Python中编码问题:u'\xe6\x97\xa0\xe5\x90\x8d' 类型的转为utf-8的解决办法

    相信小伙伴们遇到过类似这样的问题,python2中各种头疼的转码,类似u'\xe6\x97\xa0\xe5\x90\x8d' 的编码,直接s.decode()是无法解决编码问题.尝试了无数办法,都无法 ...

  9. JEECG中出现Java.sql.SQLException: Value 'xxxx' can not be represented as java.sql.Timestamp的解决办法

    出现`Java.sql.SQLException: Value 'xxxx' can not be represented as java.sql.Timestamp',其中xxxx部分对应包含一个看 ...

随机推荐

  1. PHP中使用CURL请求页面,使用fiddler进行抓包

    在PHP中使用CURL访问页面: <?php $ch = curl_init('http://www.baidu.com'); curl_setopt($ch, CURLOPT_RETURNTR ...

  2. I2C 基础原理详解

    今天来学习下I2C通信~ I2C(Inter-Intergrated Circuit)指的是 IC(Intergrated Circuit)之间的(Inter) 通信方式.如上图所以有很多的周边设备都 ...

  3. Microsoft.VisualStudio.TestTools.UnitTesting 命名空间

      类 说明 AfterAssemblyCleanupEventArgs 为 AfterAssemblyCleanup 事件提供数据. AfterAssemblyInitializeEventArgs ...

  4. 《JavaScript高级程序设计》 - 读书笔记 - 第4章 变量、作用域和内存问题

    4.1 基本类型和引用类型的值 JavaScript变量是松散类型的,它只是保存特定值的一个名字而已. ECMAScript变量包含两种数据类型的值:基本类型值和引用类型值.基本类型值指的是简单的数据 ...

  5. Jquery揭秘系列:ajax原生js实现

    讲到ajax这个东西,我们要知道两个对象XMLHTTPRequest和ActiveXObject ,提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求 ...

  6. 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题

    先要搞明白:最长公共子串和最长公共子序列的区别.    最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...

  7. DB&SQL备忘

    DB2最佳分页语句 SELECT * FROM ( SELECT inner2_.*, ROWNUMBER() OVER(ORDER BY ORDER OF inner2_) AS rownumber ...

  8. Ubuntu/mint清理系统垃圾

    Ubuntu Linux与Windows系统不同,Ubuntu Linux不会产生无用垃圾文件,但是在升级缓存中,Ubuntu Linux不会自动删除这些文件,今天就来说说这些垃圾文件清理方法.  1 ...

  9. SQL 优化tips

    1. 陷阱, 1)几个表进行join,然后过滤 等价于 2)分别过滤为小表后,再join? 并不完全.2)确实比1)效率高,但要注意一些NULL值过滤.否则2)得到的结果比1)多

  10. PHP文件大小格式化函数合集

    比如碰到一个很大的文件有49957289167B,大家一看这么一长串的数字后面单位是字节B,还是不知道这个文件的大小是一个什么概念,我们把它转换成GB为单位,就是46.53GB.用下面这些函数就可以完 ...