MVC 检测用户是否登录
2015-10-15 13:19
441 查看
当我们访问一个网站的需求检測用户是否已经登录(通过Session是否为null),我们知道在WebForm中能够定义一个BasePage类让他继承System.Web.UI.Page,重写它的OnInit()方法。在OnInit()中推断Session中是否实用户登录的信息
在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; }
步骤:
1、在Global.asax文件里为MVC程序注冊全局过滤器。 调用FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)。
FilterConfig类在App_Start目录中(创建新的MVC项目会自己主动生成)。
注意要为特性类实例的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。又跳到了登录页面,我们连登录页面都见不着肯定不能输入usernamepasswordSession也就不会有登录信息,浏览器会返回
”此网页包括重定向循环“ 的错误页面,也就是说会一直循环不停的重定向到登录页面。类似死循环,浏览器当然罢工了。
该如何解决这个bug的?
我尝试了两种解决的方法:
方法1:为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不会受全局过滤器的影响。
到这里測试一下,输入站点地址,成功进入登录页面,输入正确的usernamepassword点击登录,浏览器又返回了
的错误信息,调试了一下还是之前那个问题。仅仅只是能显示了登录页面。登录后Session["UserInfo"]有了用户。依旧会无限重定向,由于会在OnActionExecuting()在Action之前运行,这时即使Sessio["UserInfo"]!=null,也会造成死循环。解决方式:
方法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()方法。逻辑和过滤器中的代码一样。让须要进行登录校验的控制器来继承BaseController类就能够了,相当于为BaseController控制器打上了上面的校验特性。
完美解决登录校验的问题。
///<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方法。这样用户在訪问站点的时候会首先检測用户是否已经登录,假设没有登录会跳转到登录页面。
可是!
可是!问题来了,由于我们注冊的是全局的过滤器,这个过滤特性会对全部的控制器下的Action起作用,当訪问站点的时候会(比方我们注冊默认路由为/Home/Index)会首先跳转到/Home/Index,这时不会运行Index方法。会先运行OnActionExecuting()中的校验,发现Session为null,Response.Redirect("/UserLogin/Index")跳转到了登录页面。这时我们在浏览器中依旧看不到登录页面,为什么呢?还记得我们注冊的全局的过滤器。作用对象包含全部控制器下的Action当然也包含/UserLogin/Index,代码走到了这里会再次运行OnActionExecuting()方法,发现Session["UserInfo"==]null。又跳到了登录页面,我们连登录页面都见不着肯定不能输入usernamepasswordSession也就不会有登录信息,浏览器会返回
”此网页包括重定向循环“ 的错误页面,也就是说会一直循环不停的重定向到登录页面。类似死循环,浏览器当然罢工了。
该如何解决这个bug的?
我尝试了两种解决的方法:
方法1:为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不会受全局过滤器的影响。
到这里測试一下,输入站点地址,成功进入登录页面,输入正确的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()方法。逻辑和过滤器中的代码一样。让须要进行登录校验的控制器来继承BaseController类就能够了,相当于为BaseController控制器打上了上面的校验特性。
完美解决登录校验的问题。
相关文章推荐
- PHP入门
- JS中Element与Node的区别,children与childNodes的区别
- frame和Bounds的不同
- win7上安装多个Mysql1
- 2333333333333333
- webapp尺寸
- win7上安装多个Mysql1
- 苹果设备最大可用内存
- 修炼Java开发技术----在架构中体验设计模式和算法之美
- 面试遇到的局部与全局
- Linux下安装配置OpenCV
- Android 蓝牙4.0 BLE 理解
- dp、px的转换
- Java Web Filter 详解
- 与Java的邂逅
- Iterator 的小tips 以及 &
- html表格合并(行,一排)
- [Leetcode] Minimum Window Substring My Submissions Question Solution
- 完美洗牌Perfect Shuffling Algorithm
- JAVA设计模式(2) —<创建型>抽象工厂模式(Abstract Factory)