ASP.NET身份认证过程
在ASP.NET中,身份认证过程分为两个部分:
- 认证:识别当前请求的用户是否为可识别(已登录)用户;
- 授权:根据认证中识别的用户决定是否允许当前用户的请求访问指定的资源。
其中Forms认证由FormsAuthenticationModule
实现,URL授权检查由UrlAuthorizationModule
实现
认证(登录与登出的实现)
//登录
public static bool SignOn(string username,string password,bool persist)
{
InterfaceUserService userService = null;
if (userService == null)
{
userService = new UserService();
}
//此处省略参数合法性验证
//验证用户名密码是否正确,若正确则设置Cookie
if (userService.Validate(username, password))
{
SetAuthenticationTicket(username, persist);
HttpCookie authCookie = FormsAuthentication.GetAuthCookie(username,persist);
HttpContext.Current.Response.Cookies.Remove(authCookie.Name);
HttpContext.Current.Response.Cookies.Add(authCookie);
return true;
}
else
{
return false;
}
}
//登出
public static void LogOut()
{
HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName);
//使cookie强制过期
authCookie.Expires = DateTime.Now.AddYears(-30);
authCookie.Path = HttpContext.Current.Request.ApplicationPath;
HttpContext.Current.Response.Cookies.Add(authCookie);
//退出登录后执行页面重定向到主页操作
}
//获取登录用户名部分代码,AuthenticationMoudel类中的UserName属性
public string UserName
{
get
{
var httpContext = HttpContext.Current;
if (httpContext != null &&
httpContext.Request != null &&
httpContext.Request.IsAuthenticated)
{
try
{
return httpContext.User.Identity.Name;
}
catch
{
}
}
else
{
return null;
}
}
}
对于Forms认证,我们需要在Web.config
的
该部分指定了身份验证模式为Forms,Cookie的使用方式,Cookie名称,默认登录页面(当未认证或认证失败时会跳转到默认登录页)。
为何要设置Cookie呢?
因为Forms的身份认证是通过Cookie来维持的,且该Cookie是加密过的HttpOnly Cookie(无法在浏览器端更改的Cookie)
授权
授权的问题就是用户与用户组权限的问题,根据当前登录用户及其所属用户组的权限来判断当前用户的请求是否能够访问目标资源。
Forms身份认证的授权也需要在Web.config
的
自定义验证用户登录
一、Filter
ASP.NetMVC模式自带的过滤器Filter,是一种声明式编程方式,支持四种过滤器类型,分别是:Authorization(授权),Action(行为),Result(结果)和Exception(异常)。
表1
过滤器类型 | 接口 | 描述 |
---|---|---|
Authorization | IAuthorizationFilter | 此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法 |
Action | IActionFilter | 用于进入行为之前或之后的处理 |
Result | IResultFilter | 用于返回结果的之前或之后的处理 |
Exception | IExceptionFilter | 用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常 |
但是默认实现它们的过滤器只有三种,分别是ActionFilter(方法),Authorize(授权),HandleError(错误处理);各种信息如下表所示:
表2
过滤器 | 类名 | 实现接口 |
---|---|---|
Authorize | AuthorizeAttribute | IAuthorizationFilter |
HandleError | HandleErrorAttribute | IExceptionFilter |
自定义 | ActionFilterAttribute | IActionFilter和IResultFilter |
ASP.NET默认的身份验证过滤器是[Authorize]对应AuthorizeAttribute类
二、通过自定义过滤器实现登录验证
表2中只写了实现表1中的接口,实际上ActionFilterAttribute继承了FilterAttribute、IActionFilter和IResultFilter.
具体实现方法
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class AuthenticatedAttribute:FilterAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
//此处AuthenticationMoudel类中的UserName属性已在认证模块中定义
if (string.IsNullOrEmpty(AuthenticationMoudel.UserName))
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
最后在需要登录验证的地方打下自定义的Filter的标签[Authenticated]
[Authenticated]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "欢迎使用 ASP.NET MVC!";
return View();
}
}
三、使用系统的AuthorizeAttribute验证登录
public class AuthenticationAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
//base.OnAuthorization(filterContext);
//如果控制器没有加AllowAnonymous特性或者Action没有加AllowAnonymous特性才检查
if (!filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute),true) && !filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute),true))
{
//此处写判断是否登录的逻辑代码
HttpCookie cookie = filterContext.HttpContext.Request.Cookies["Member"];
if (!(cookie!=null && cookie.Values["name"] == "test" && cookie.Values["pass"] == "123")) {
filterContext.Result = new RedirectResult("/Member/Login");
}
}
}
}
若加了Authentication过滤器的控制器中有需要匿名访问的方法,可以在方法前面添加[AllowAnonymous]过滤器
另一种写法是继承FilterAttribute 并实现接口IAuthorizationFilter,方式与系统的AuthorizeAttribute类似
参考文章:1. 细说ASP.NET Forms身份认证
2. ASP.Net MVC Filter验证用户登录
菜鸟一枚,还望大家多多指教
补充:在运行上述代码时,发现配置了Forms认证后登录不成功,匿名用户访问需要认证的页面时不能跳转到登录页面,解决方案如下:
在Web.Config文件的节添加下面两句
刚开始我只有第一句
,添加第二句后解决问题。