当我们访问一个网站的需求检測用户是否已经登录(通过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 voidOnInit(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 overridevoid OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
if (IsCheck)
{
//校验用户是否已经登录
if (filterContext.HttpContext.Session["loginUser"] ==null)
{ //跳转到登陆页
filterContext.HttpContext.Response.Redirect("/UserLogin/Index"); }
}
else{ //跳转到首页
filterContext.HttpContext.Response.Redirect("/Home/Index");
}
}<span style="font-size:14px;">怎么让这个过滤器起作用呢?</span>

步骤:

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 voidRegisterGlobalFilters(GlobalFilterCollection filters)
{ //filters.Add(newHandleErrorAttribute());
filters.Add(newLoginCheckFilterAttribute() { IsCheck = true }); }
}

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

这样子。LoginCheckFilterAttribute这个特性就会对整个MVC程序中的控制器和Action起作用了。就是说在运行Action方法之前会先调用特性类中的重写OnActionExecuting方法。这样用户在訪问站点的时候会首先

rs=1&u=http%3A%2F%2Fwww%2Eth7%2Ecn%2FProgram%2Fnet%2F201310%2F155618%2Eshtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=smileking_cpr&k=%BC%EC%B2%E2&k0=%B9%FD%C2%CB%C6%F7&kdi0=1&k1=%BF%D8%D6%C6%C6%F7&kdi1=1&k2=%BC%EC%B2%E2&kdi2=8&k3=web&kdi3=8&k4=%E4%AF%C0%C0%C6%F7&kdi4=8&k5=%CE%A2%C8%ED&kdi5=8&sid=199e25bf6af034ca&ch=0&tu=u1682280&jk=8459ddaa3461f5e6&cf=29&fv=15&stid=9&urlid=0&luki=3&seller_id=1&di=128" target="_blank">检測用户是否已经登录,假设没有登录会跳转到登录页面。

可是!

可是!问题来了,由于我们注冊的是全局的过滤器,这个过滤特性会对全部的控制器下的Action起作用,当訪问站点的时候会(比方我们注冊默认路由为/Home/Index)会首先跳转到/Home/Index,这时不会运行Index方法。会先运行OnActionExecuting()中的校验,发现Session为null,Response.Redirect("/UserLogin/Index")跳转到了登录页面。这时我们在浏览器中依旧看不到登录页面,为什么呢?还记得我们注冊的全局的过滤器。作用对象包含全部

rs=1&u=http%3A%2F%2Fwww%2Eth7%2Ecn%2FProgram%2Fnet%2F201310%2F155618%2Eshtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=smileking_cpr&k=%BF%D8%D6%C6%C6%F7&k0=%B9%FD%C2%CB%C6%F7&kdi0=1&k1=%BF%D8%D6%C6%C6%F7&kdi1=1&k2=%BC%EC%B2%E2&kdi2=8&k3=web&kdi3=8&k4=%E4%AF%C0%C0%C6%F7&kdi4=8&k5=%CE%A2%C8%ED&kdi5=8&sid=199e25bf6af034ca&ch=0&tu=u1682280&jk=8459ddaa3461f5e6&cf=29&fv=15&stid=9&urlid=0&luki=2&seller_id=1&di=128" target="_blank">控制器下的Action当然也包含/UserLogin/Index,代码走到了这里会再次运行OnActionExecuting()方法,发现Session["UserInfo"==]null。又跳到了登录页面,我们连登录页面都见不着肯定不能输入usernamepasswordSession也就不会有登录信息,浏览器会返回
”此网页包括重定向循环“ 的错误页面,也就是说会一直循环不停的重定向到登录页面。类似死循环,浏览器当然罢工了。

该如何解决这个bug的?

我尝试了两种解决的方法:

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

[LoginCheckFilterAttribute(IsCheck= false)]  //打上用户登录校验特性(IsCheck设为false不让它对此

rs=1&u=http%3A%2F%2Fwww%2Eth7%2Ecn%2FProgram%2Fnet%2F201310%2F155618%2Eshtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=smileking_cpr&k=%BF%D8%D6%C6%C6%F7&k0=%B9%FD%C2%CB%C6%F7&kdi0=1&k1=%BF%D8%D6%C6%C6%F7&kdi1=1&k2=%BC%EC%B2%E2&kdi2=8&k3=web&kdi3=8&k4=%E4%AF%C0%C0%C6%F7&kdi4=8&k5=%CE%A2%C8%ED&kdi5=8&sid=199e25bf6af034ca&ch=0&tu=u1682280&jk=8459ddaa3461f5e6&cf=29&fv=15&stid=9&urlid=0&luki=2&seller_id=1&di=128" target="_blank">控制器起作用,而对其它控制器和Action起作用,防止重定向循环)   
public class UserLoginController :Controller    {    ...     }

我们在定义这个特性类的时候 有个bool属性 IsCheck,它表示是否校验,这里设为false表示不校验。

顺便说一下LoginCheckFilterAttribute能够省略Attrbute后缀。

一定要在控制器上打这个特性,不要仅仅针对下边的某个Action,由于这里边有生成验证码的Action和处理登录请求的Action。它们都不须要进行session校验(没意义),在控制器上打上特性会对它下边的全部Action起作用,不用为每一个Action打特性了,节省代码量。我们注冊了全局过滤器,又单独为UserLoginController控制器打上过滤特性,这里有一个优先级的问题Action>Controller>全局。UserLoginController不会受全局过滤器的影响。

到这里測试一下,输入站点地址,成功进入登录页面,输入正确的usernamepassword点击登录,浏览器又返回了

的错误信息,调试了一下还是之前那个问题。仅仅只是能显示了登录页面。登录后Session["UserInfo"]有了用户。依旧会无限重定向,由于会在OnActionExecuting()在Action之前运行,这时即使Sessio["UserInfo"]!=null,也会造成死循环。解决方式:

运行时出报异常。这时要在Global.asax里加入:开启Session功能

 public class WebApiApplication : System.Web.HttpApplication

    {

        public override void Init()

        {

            this.PostAuthenticateRequest += (sender, e) => HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);

            base.Init();

        }

}

方法2:利用BaseController类(类似WebFrom的BasePage)

1、新建一个BaseController类,继承System.Web.Mvc.Controller,类中定义一个UserInfo属性,保存从Session["UserInfo"]中拿出的用户实体。方便他的派生类调用。

2、F12定义一下System.Web.Mvc.Controller这个类发现

public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter,IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IController,IAsyncManagerContainer   
{       //...}

它居然也实现了IActionFilter接口,那就用不着上面我们的全局过滤器了。仅仅须要重写OnActionExecuting()方法。逻辑和过滤器中的代码一样。让须要进行登录校验的

rs=1&u=http%3A%2F%2Fwww%2Eth7%2Ecn%2FProgram%2Fnet%2F201310%2F155618%2Eshtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=smileking_cpr&k=%BF%D8%D6%C6%C6%F7&k0=%B9%FD%C2%CB%C6%F7&kdi0=1&k1=%BF%D8%D6%C6%C6%F7&kdi1=1&k2=%BC%EC%B2%E2&kdi2=8&k3=web&kdi3=8&k4=%E4%AF%C0%C0%C6%F7&kdi4=8&k5=%CE%A2%C8%ED&kdi5=8&sid=199e25bf6af034ca&ch=0&tu=u1682280&jk=8459ddaa3461f5e6&cf=29&fv=15&stid=9&urlid=0&luki=2&seller_id=1&di=128" target="_blank">控制器来继承BaseController类就能够了,相当于为BaseController控制器打上了上面的校验特性。
完美解决登录校验的问题。

版权声明:本文博主原创文章。博客,未经同意不得转载。

MVC 检测用户是否登录的更多相关文章

  1. day108:MoFang:首页检测用户是否登录&在项目中使用MongoDB&用户页面更新用户信息&交易密码界面实现

    目录 1.首页页面也要检测用户是否登录 2.在flask中使用MongoDB 3.用户页面更新用户信息 4.交易密码界面/密码修改界面/昵称修改界面初始化 5.交易密码实现 1.首页页面也要检测用户是 ...

  2. [转]MVC 检测用户是否已经登录

    本文转自:http://blog.csdn.net/jayzai/article/details/41252137 当我们访问某个网站的时候需要检测用户是否已经登录(通过Session是否为null) ...

  3. Mvc校验用户没有登录就跳转的实现

    看字面意思很简单,就是判断用户是否登录了,如果没有登录就跳转到登陆页面. 没错,主要代码如下(这里就不写判断登录了,直接跳转) 首先在控制器中新建一个BaseController public cla ...

  4. ThinkPHP - 每个操作都检测用户是否登录

    TP提供了一个自动执行的函数_initialize(), 你创建一个公共控制器CommonAction.class.php文件. 定义了此方法,不能存在构造方法__construct() <?p ...

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

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

  6. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(12)-实现用户异步登录和T4模板

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(12)-实现用户异步登录和T4模板 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建  ...

  7. MVC学习笔记:MVC实现用户登录验证ActionFilterAttribute用法并实现统一授权

    在项目下新建一个文件夹来专门放过滤器类,首先创建一个类LoginFilter,这个类继承ActionFilterAttribute.用来检查用户是否登录和用户权限.: using System; us ...

  8. [转载]MVC中单用户登录

    转自:http://www.cnblogs.com/firstcsharp/archive/2013/05/19/3087481.html 把下面这段代码放在登录用户验证以后:   //用户登录验证通 ...

  9. asp.net mvc 自定义全局过滤器 验证用户是否登录

    一般具有用户模块的系统都需要对用户是否登录进行验证,如果用户登录了就可以继续操作,否则退回用户的登录页面 对于这样的需求我们可以通过自定义一个独立的方法来完成验证的操作,但是这样代码的重复率就大大提高 ...

随机推荐

  1. 慎得慌风 656ik67o

    http://photo.163.com/q/7634581 http://photo.163.com/q/7634580 http://photo.163.com/q/7634577 http:// ...

  2. JAVA线程相互排斥问题

    public class TraditionalThreadSynchonized { public static void main(String[] args) { final OutPuter ...

  3. 拿到阿里,网易游戏,腾讯,smartx的offer的过程 (转)

    前言 从今年的3月14日阿里的电话面试开始,到现在4月16日在西安悦豪酒店进行的腾讯HR面到现在一个多月了,中间先后收到了阿里,网易游戏,腾讯和smartx的offer,今天早晨刚刚接到了腾讯HR的电 ...

  4. Thrift反序列化导致OOM(转)

    概述 最近线上的日志处理服务偶尔会出现Out Of Memory的问题,从Exception的call stack中顺藤摸瓜,最终定位到是thrift反序列化的问题. 发现问题 先交代一下问题现场: ...

  5. poj3278(bfs)

    题目链接:http://poj.org/problem?id=3278 分析:广搜,每次三种情况枚举一下,太水不多说了. #include <cstdio> #include <cs ...

  6. Spring3.0官网文档学习笔记(七)--3.4.2

    3.4.2 依赖与配置的细节     3.4.2.1  Straight values (primitives, Strings, and so on)     JavaBeans PropertyE ...

  7. android中更改spinner、AutoCompleteTextView切割线的颜色

    话说去除切割线的方法找了非常久也没找到,最终发现了更改切割线的方法 spinner和AutoCompleteTextView提示列表中间有一条黑色的切割线.想要改变它的颜色值,就要重写style. 1 ...

  8. Cocos2d-x v3.0正式版尝鲜体验【3】 Label文本标签

    Cocos2d-x在新版本号中增加了新的Label API.和以往不同的是,2.x的版本号是通过三个不同的类来创建不同的文本标签,而如今是模仿着精灵的创建方式.一个类创建不同形式的文本,只是核心内容还 ...

  9. 恩布企业 IM 安卓端 1.3,服务端 1.12 公布

    恩布企业IM的 Android 安卓开源手机client EntboostIM 公布 1.3 版本号.同一时候恩布IM服务端更新至 1.12 版本号; 安卓端主要更新内容: 添加收发手机文件功能: 登 ...

  10. ASIHttpRequest 摘要

    向server端上传数据 ASIFormDataRequest ,模拟 Form表单提交,其提交格式与 Header会自己主动识别. 没有文件:application/x-www-form-urlen ...