ASP.NET MVC中的身份验证

传统的登录验证方式,是通过将用户的登录状态信息保存在服务端的Session中,再利用客户端浏览器的Cookie保存SessionID,这样浏览器每次在向服务端发起请求时,都会携带该Cookie值,服务端可以根据相应的SessionID来获取匹配的Session信息,并进行验证。

在ASP.NET MVC中,可以通过使用过滤器来在请求的处理过程中,执行一些统一或额外的操作。

过滤器种类
过滤器类型 接口默认实现说明
AuthorizationIAuthorizationFilterAuthorizeAttribute在其他过滤器执行前运行,用于控制对指定Controller或Action的访问,必须满足授权要求。
ActionIActionFilterActionFilterAttribute在Action执行之前或之后运行。
ResultIResultFilterActionFilterAttribute在结果返回之前或之后运行。
ExceptionIExceptionFilterHandleErrorAttribute用于处理由指定Controller或Action中引发的异常。

AuthorizeAttribute可以限制指定的Controller或Action,只能够被满足授权要求的用户进行访问。

当使用AuthorizeAttribute标记一个Controller时,如果希望允许某些Action可以被匿名访问,则可以在该Action上标记AllowAnonymousAttribute。

[Authorize]
public class HomeController : Controller
{
    /// <summary>
    /// 首页
    /// </summary>
    /// <returns></returns>
    public ActionResult Index()
    {
        return View();
    }

    /// <summary>
    /// 登录页
    /// </summary>
    /// <returns></returns>
    [AllowAnonymous]
    public ActionResult Login(string account, string password)
    {
        if (string.IsNullOrEmpty(account))
        {
            return View();
        }
        System.Web.Security.FormsAuthentication.SetAuthCookie(account, false);
        return this.RedirectToAction("Index");
    }
}

一个简单的Demo如下所示:

首先,需要在Web.config中的system.web节点下添加以下内容:

<authentication mode="Forms">
  <forms loginUrl="~/Home/Login" name="login"></forms>
</authentication>

<authorization> 用于配置 ASP.NET 身份验证方案,mode用于指定应用程序的默认身份验证模式,取值范围共分为 Windows、Form、Passport、None 四种验证模式。

<forms>用于配置 基于窗体的自定义身份验证,其中的loginUrl用于设置在没有找到任何有效的身份验证的Cookie时,重定向到登录页面的URL,其默认值为 login.aspx;name则设置了用于存储身份验证信息的Cookie名称,默认值为 ".ASPXAUTH";

接着,在需要进行身份验证的Action上使用AuthorizeAttribute进行标记:

/// <summary>
/// 首页
/// </summary>
/// <returns></returns>
[Authorize]
public ActionResult Index()
{
    return View();
}

最后,只需在执行登录操作的Action中调用System.Web.Security.FormsAuthentication类的SetAuthCookie方法,将登录信息写入到Cookie中即可。

/// <summary>
/// 登录页
/// </summary>
/// <returns></returns>
public ActionResult Login(string account, string password)
{
    if (string.IsNullOrEmpty(account))
    {
        return View();
    }
    System.Web.Security.FormsAuthentication.SetAuthCookie(account, false);
    return this.RedirectToAction("Index");
}

当直接访问Index页面时,因为没有登录信息,所以页面将会被重定向到Login页。而在完成登录操作之后,身份验证信息将被写入到Cookie中,此时可以通过浏览器的开发者工具,查看到Cookie信息,其名称“login”正是上面在forms标签中所设置的名称。

在此之后就可以正常访问Index页面了。

此外,通过forms中的timeout可以用来手动设置存储身份验证信息的Cookie的过期时间。timeout以整数分钟为单位,其默认值为30。当slidingExpiration的值为True时,表示在距离最后一次访问的N分钟后过期,相当于在单个会话期间内,每次请求都将刷新过期时间。而False则相当于过期时间是一个绝对值,只要大于该间隔范围就会立即过期。slidingExpiration的默认值为 True。

在forms中还包含了许多其他的特性,具体可以参考MSDN。

在退出登录时,可以使用 System.Web.Security.FormsAuthentication.SignOut() 来从浏览器删除 Forms 身份验证的票证信息,实现注销功能。

/// <summary>
/// 注销
/// </summary>
/// <returns></returns>
[Authorize]
public ActionResult Logout()
{
    System.Web.Security.FormsAuthentication.SignOut();
    return this.RedirectToAction("Login");
}

除了使用默认实现的AuthorizeAttribute类之外,还可以通过继承AuthorizeAttribute类,实现自定义的权限验证:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AuthenticationAttribute : AuthorizeAttribute
{
    // 执行顺序:OnAuthorization-->AuthorizeCore-->HandleUnauthorizedRequest

    /// <summary>
    /// 请求授权处理
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        // 如果当前Action或Controller标记了AllowAnonymousAttribute,则跳过结束验证
        if (filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
        {
            return;
        }

        // 此外,通过 filterContext.Controller 还可以获得 ViewData 或 ViewBag,可以用来存储一些临时的数据内容:
        // filterContext.Controller.ViewData
        // filterContext.Controller.ViewBag



        // 实际上,基类所实现的 OnAuthorization 中,已经包含了对 AllowAnonymousAttribute 的验证
        // 这也是为什么直接标记 AuthorizeAttribute ,在遇到 AllowAnonymousAttribute 会跳出验证的原因

        // 并且,在基类的 OnAuthorization 中,还负责调用了 OnAuthorization 方法
        // 如果 OnAuthorization 的返回值为 false,则将调用 HandleUnauthorizedRequest 方法
        base.OnAuthorization(filterContext);
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        //return base.AuthorizeCore(httpContext);

        // 拿到存储有身份信息的cookie对象
        var cookies = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];

        // 如果没有拿到cookie信息,则说明当前用户尚未登录
        if (cookies == null)
        {
            return false;
        }

        // 解码认证信息
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookies.Value);
        // 拿到解密后的票据信息 
        string userData = ticket.UserData;

        // ......

        return true;
    }
    // 当AuthorizeCore返回false时,将会调用 HandleUnauthorizedRequest
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        //base.HandleUnauthorizedRequest(filterContext);
        filterContext.Result = new RedirectResult("~/Default/Login");
    }
}

如果希望对所有的请求都应用授权过滤的话(比如统一的登录状态验证),不必为每一个Controller都单独手动的标记特性,而是可以在Global文件的Application_Start中,添加全局筛选:
GlobalFilters.Filters.Add(new AuthenticationAttribute());

而对于一些不希望进行授权验证的特殊的Controller或Action,只需标记为它们AllowAnonymousAttribute即可。

在下入门不久,还是嘎嘎新的一个幼小菜鸟,记录一下平时的学习心得,如有错误,还请诸位大神海涵轻拍,必及时更正!

参考资料

authentication 元素(ASP.NET 设置架构) | Microsoft Docs

authentication 的 forms 元素(ASP.NET 设置架构) | Microsoft Docs

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值