前言当我们访问某个网站的时候需要检测用户是否已经登录(通过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. Memcached telnet端命令

    Command Description Example get Reads a value get mykey set Set a key unconditionally set mykey 0 60 ...

  2. webpack --- 详解

    官网: http://webpack.github.io/docs/using-loaders.html 简书: http://www.jianshu.com/p/42e11515c10f

  3. 86 ipmitools-查看硬件信息工具

    1.简介 IPMI(Intelligent Platform Management Interface)即智能平台管理接口是使硬件管理具备"智能化"的新一代通用接口标准.用户可以利 ...

  4. 一些js 插件的作用

    前言: 从一些开源网站上下载下来的 后台管理系统模板一般会有很多的js ,其js 的功能是什么呢?这里随手查询了一下,记录下来 正文: 1.zDialog.js 各种弹窗插件详细案例:http://w ...

  5. UI: 窗口全屏, 窗口尺寸

    窗口全屏 窗口尺寸 示例1.窗口全屏UI/FullScreen.xaml <Page x:Class="Windows10.UI.FullScreen" xmlns=&quo ...

  6. iis虚拟目录名称“ReportServer”的巧合

      今天测试一个Crystal Report网站的报表服务,建立一个虚拟目录,名为ReportServer,结果无论怎样访问浏览器都返回 localhost/ReportServer - / Micr ...

  7. Let & Const

    Let & Const let 基础用法 很简单就能说明这个问题 if(false) { var a = 'heihei' } a = undefined if(true) { var a = ...

  8. 转 PresentViewController切换界面

    视图切换,没有NavigationController的情况下,一般会使用presentViewController来切换视图并携带切换时的动画, 其中切换方法如下: – presentViewCon ...

  9. python基础2(数据类型、数据运算、for循环、while循环、列表)

    1.数据类型 python使用对象模型来存储数据,每一个数据类型都有一个内置的类,每新建一个数据,实际就是一个对象,即所有数据都是对象. 对象的3个特性: 身份:即内存地址,可以用id()来获取 类型 ...

  10. 【转载】Arcengine效率探究之二——属性的更新

    文转载自hymyjl2010<Arcengine效率探究之二——属性的更新>   修改一批要素的属性有多种方法,当数据量较大时,若选择不当可能会大大影响速度. 一.IRowBuffer 方 ...