AOP实践--利用MVC5 Filter实现登录状态判断
2018-01-07 18:17 狼人:-) 阅读(842) 评论(0) 编辑 收藏 举报1、定义一AuthenAdminAttribute特性类
- public class AuthenAdminAttribute : FilterAttribute, IAuthenticationFilter
- {
- public void OnAuthentication(AuthenticationContext filterContext)
- {
- //这个方法是在Action执行之前调用
- var user = filterContext.HttpContext.Session["AdminUser"];
- if (user == null)
- {
- //filterContext.HttpContext.Response.Redirect("/Account/Logon");
- var Url = new UrlHelper(filterContext.RequestContext);
- var url = Url.Action("Logon", "Account", new { area=""});
- filterContext.Result = new RedirectResult(url);
- }
- }
- public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
- {
- //这个方法是在Action执行之后调用
- }
- }
是否登录是通过Session键值为AdminUser的值是否为null判断,如果为null也就是还没有登录或者过期了,就跳转到登录页面,即"/Account/Logon"。
注意:上面OnAuthentication是在最开始被调用的,也在ActionFilter方法之前。而OnAuthenticationChallenge方法是在Action执行之后,返回视图之前被调用。所以要把登录验证写在方法OnAuthentication中。而且在里面我们用到了设置filterContext.Result = new RedirectResult(url);而不是跳转的形式,很关键的。MVC在执行Filter时,如果我们手动用一个ActionResult对象指定了其Context对象的Result属性的值,那么这个这个ActionResult将作为这个请求的结果输出,并且在这次请求管道中剩下的步骤将不再继续执行。反之如果没有设置filterContext.Result的值,它会继续执行接下来的步骤,甚至是Action方法,就算我们设置了跳转。
2、定义登录Controller
- public class ManageController : Controller
- {
- public ActionResult Logon()
- {
- return View();
- }
- [HttpPost]
- public ActionResult Logon(string username,string password)
- {
- if (username == "admin" && password == "admin")
- {
- Session["AdminUser"] = username;
- return RedirectToAction("Index",
- "Order", new { area = "Admin" });
- }
- else
- ViewBag.Error = "用户名或密码不正确!";
- return View();
- }
- public ActionResult LogOff()
- {
- if (Session["AdminUser"] != null)
- {
- Session["AdminUser"] = null;
- }
- return RedirectToAction("Logon");
- }
- }
Action名为Logon的方法就是里面就是登录相关逻辑,这里的逻辑我为了简单化,就直接把用户名和密码固定写死了。当然实际过程中你可以根据你自己的需要,比如结合数据库表记录来判断用户名密码是否合法,如果合法就相应的信息存在Session里面,当然你也可以存在Cookie里。
注意:这里登录成功之后的存Session的key一定要和上面第一步的AuthenAdminAttribute用到的key一致。
3、设置需要登录判断的Controller或者Action
- [AuthenAdmin]
- public class CategoryController : Controller
- {
- public ActionResult Index()
- {
- //此处省略具体逻辑代码
- return View();
- }
- }
上面是对整个Controller都要登录验证,就是这个Controller的所有Action必须要登录才能访问。那如果要针对单独的一个Action控制,其它不做要求呢?这也很好办。代码这样写就可以了。
- public class CategoryController : Controller
- {
- public ActionResult Index()
- {
- //此处省略具体逻辑代码
- return View();
- }
- [AuthenAdmin]
- public ActinResult List()
- {
- //此处省略具体逻辑代码
- return View();
- }
- }
- public class CustomAuthAttribute : AuthorizeAttribute {
- private bool localAllowed;
- public CustomAuthAttribute(bool allowedParam) {
- localAllowed = allowedParam;
- }
- protected override bool AuthorizeCore(HttpContextBase httpContext) {
- var user = httpContext.Session["AdminUser"];
- return user != null
- }
- }
可以看到AuthorizeAttribute核心方法是AuthorizeCore返回值是一个bool类型,也就是只能判断是否登录过了,这种情况如果你的系统采用Form验证这个,确实是一个简单可行的方案。如果要涉及到更加细微的权限控制或者要把登录信息存储到Session或者其实地方就不太好办了,因为ASP.NET的Form验证是基于Cookie的。所以我一般建议自己实现接口IAuthenticationFilter,这样让我们的系统更加灵活,更加容易扩展和控制。
这样最后来看我们的业务逻辑代码不会有身份验证相关的代码,登录验证和业务逻辑代码完全隔离开了,业务逻辑代码变得简洁了许多,这就是我理解的:你只需要针对一方面编程,也就是AOP提倡的面向方面编程。AOP技术让我们的软件模块之间的耦合性降低,大大的提高的我们软件的可维护性和可复用性,AOP你值得拥有。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南