在我们日常开发的绝大多数系统中,都涉及到管理用户的登录和授权问题。登录功能(Authentication),针对于所有用户都开放;而授权(Authorization),则对于某种用户角色才开放。
在asp.net mvc中,微软虽然已经帮助开发者构建了ASP.NET Identity
这样强大的验证授权框架,但是如果想定制更多的逻辑功能的话,还得自己动动手。
根据日常的开发经验,我总结了大概下面2种方法:
a) 在我最早的时候,比较单纯,也许是从WebForm
那里学来的招式,我并没有细读Controller
里的所有方法,所以在派生类里自己添加了验证方法,然后在每个Action
方法里调用。此方法现在看来有些蛋疼...
派生类如下:
public class AuthenticationControllor : Controller
{
public bool Validate()
{
if (Session["username"] == null)
return false;
else
return true;
}
public ActionResult RedirectLogin(bool redirect = true)
{
if (redirect)
return RedirectToAction("Login", "Home", new { from = Request.Url.ToString() });
else
return RedirectToAction("Login", "Home");
}
}
使用类如下:
public class HomeController : AuthenticationControllor
{
public ActionResult Index()
{
if (!Validate())
return RedirectLogin();
return View();
}
}
b) 后来学习了很多人的代码后,发现在Controller
里有一个OnActionExecuting
方法,此方法是在Action
之前执行的,非常方便。
派生类如下:
public class AuthenticationControllor : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Session["username"] == null)
filterContext.Result = new RedirectToRouteResult("Login", new RouteValueDictionary { { "from", Request.Url.ToString() } });
base.OnActionExecuting(filterContext);
}
}
使用类如下:
// 不需要多写任何逻辑代码就能判断是否登录并跳转
public class HomeController : AuthenticationControllor
{
public ActionResult Index()
{
return View();
}
}
由于继承Controller
方法不太适合一个Controller
下的有些Action
需要登录有些Action
不需要登录的场景,所以针对每个Action
写一个统一的特性会更好一些。
ActionFilterAttribute
里也有OnActionExecuting
方法,跟Controller
一样, 同是抽象实现了IActionFilter
接口。
派生类如下:
// 登录认证特性
public class AuthenticationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Session["username"] == null)
filterContext.Result = new RedirectToRouteResult("Login", new RouteValueDictionary { { "from", Request.Url.ToString() } });
base.OnActionExecuting(filterContext);
}
}
使用方法如下:
public class HomeController : Controller
{
[Authentication]
public ActionResult Index()
{
return View();
}
}
如果你想针对整个MVC项目的所有Action
都使用此过滤器,步骤如下:
a) 确保Global.asax.cs
的Application_Start
方法中包含如下第8行:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
b) 在FilterConfig.cs
文件中注册相应的特性过滤器:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new AuthenticationAttribute());
}
}
推荐大家使用第2种过滤器的方法实现认证和授权。