引言

大家都知道Http是无状态的协议,所以访问一个url,你并不能知道用户在之前是否已经登陆过。但是许多业务上的逻辑又离不开user的信息,这个时候就可以借助身份认证来记录当前user的登录状态。这其中Forms身份认证是最常见的身份认证。

这篇博客讲的内容就是结合一个最普通的MVC工程来讲解下Forms身份认证是怎么实现记录用户登录状态的。并说下怎么自定义一个身份认证。

Forms身份认证

打开Visual Studio 2013,新建Asp.net web mvc application,选择Internet Application

建好之后,按F5就能看到新建的网站。

修改Index,cshtml:

@if (Request.IsAuthenticated)
{
<text>用户已登录:</text>
@Context.User.Identity.Name
}
else
{
<text>用户未登录</text>
}

运行之后,你能看到:

继续修改Index.cshtml

@if (Request.IsAuthenticated)
{
<text>用户已登录:</text>
@Context.User.Identity.Name
}
else
{
<text>用户未登录</text>
<form method="post" action="@Request.RawUrl">
<input type="text" name="userName" />
<input type="submit" value="Submit" />
</form>
}

在对应的HomeController里加上对应的方法:

 [HttpPost]
public ActionResult Index(string id)
{
string userName = Request.Params["userName"];
FormsAuthentication.SetAuthCookie(userName, true);
return Index();
}

按F5运行之后,在输入框内填上user name,运行之后的结果:

注意上述的结果都是在web.config里开启Forms认证的基础上

<authentication mode="Forms">
</authentication>
内部运行机理

Forms身份认证的核心类是FormsAuthenticationModule

它是一个http module,实现了接口IHttpModule,这个接口的主要方法:

Init(HttpApplication Context)

看FomrsAuthenticationModule的实现

         public void Init(HttpApplication app)
{
if (!_fAuthChecked)
{
_fAuthRequired = AuthenticationConfig.Mode == AuthenticationMode.Forms;
_fAuthChecked = true;
}
if (_fAuthRequired)
{
FormsAuthentication.Initialize();
app.AuthenticateRequest += new EventHandler(this.OnEnter);
app.EndRequest += new EventHandler(this.OnLeave);
}
}

解释下代码,这个方法首先判断是否开启了Forms 认证,如果是Forms认证,就注册了两个HttpApplication管道事件AuthenticateRequest和EndRequest,继续看下

注册的AuthenticateRequest事件

 HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
this.OnAuthenticate(new FormsAuthenticationEventArgs(context));

找到了最核心的方法OnAuthenticate

由于此方法比较长,笔者只摘录出最核心的几句话

FormsAuthenticationTicket tOld = ExtractTicketFromCookie(e.Context, FormsAuthentication.FormsCookieName, out cookielessTicket);
e.Context.SetPrincipalNoDemand(new GenericPrincipal(new FormsIdentity(ticket), new string[]));

可以看出最核心的方法是Forms module从http context中的Cookie中解析出FormsAuthenticationTicket对象,然后new出来FormsIdentity,最后传给HttpContext

module一般都是注册Application管道事件,在事件里实现自己的核心处理,比如MVC,也是Module,实现自己的UrlRoutingModule,注册ResolveRequestCache事件

拓展:Authorization

Authorization可以控制user对网站的访问权限,比如哪种user可以访问哪种资源

在上述的工程web.config里加上

    <authentication mode="Forms">
<forms loginUrl="~/Home/Index"/>
</authentication>
<authorization>
<deny users="?"/>
</authorization>

deny users="?"代表只有登录用户才可以访问网站

于此对应的还有allow users="*" 允许任何用户可以访问

此类功能是UrlAuthorizationModule 实现,在此不在赘述,实现方式和FormsAuthenticationModule方式大同小异。

自定义身份认证

在某些业务功能里,需要cookie记住的功能不仅仅是user name,比如remember me功能,这个时候就可以用自定义身份认证来实现。

至于实现方式,既然已经知道Forms身份认证怎么实现,完全可以比葫芦画瓢实现自己需要的认证

下面写一个简单的实例

首先仿照FormsAuthenticationModule,注册AuthenticateRequest事件

         protected void Application_AuthenticateRequest()
{
HttpContext context = HttpContext.Current;
if (!context.Request.RawUrl.Equals("/"))
{
HttpCookie cookie = context.Request.Cookies["CustomCookie"];
string[] strs = cookie.Value.Split('x');
bool rememberMe = Convert.ToInt32(strs[]) == ? true : false;
HttpContext.Current.User = new CustomPrincipal(new CustomIdentity(strs[], rememberMe));
}
}

标注:

context.Request.RawUrl.Equals("/") 此句是简单的将Index.cshtml作为登录页面,实际应用中当然需要修改下。

其中CustomPrincipal和CustomIdentity类的代码如下

     public class CustomPrincipal : IPrincipal
{
private IIdentity identity; public CustomPrincipal(IIdentity identity)
{
this.identity = identity;
} public IIdentity Identity
{
get { return identity; }
} public bool IsInRole(string role)
{
throw new NotImplementedException();
}
} public class CustomIdentity : IIdentity
{ private string name;
private bool rememberMe; public CustomIdentity(string name, bool rememberMe)
{
this.name = name;
this.rememberMe = rememberMe;
} public string AuthenticationType
{
get { return string.Empty; }
} public bool IsAuthenticated
{
get { return true; }
} public string Name
{
get { return name; }
}
}

Index.cshtml继续作为登录页面,对应的登录方法:

         [HttpPost]
public ActionResult Index(string id)
{
string userName = Request.Params["userName"];
HttpCookie cookie = new HttpCookie("CustomCookie");
cookie.Value = userName + "x" + .ToString();
cookie.Expires = DateTime.Now.AddHours();
System.Web.HttpContext.Current.Response.SetCookie(cookie);
return RedirectToAction("About");
}

About.cshtml作为判断是否登录的页面

 @if (Request.IsAuthenticated)
{
<text>用户已登录:</text>
@Context.User.Identity.Name
}
else
{
<text>用户未登录</text>
}

最后运行结果:

到此,整篇博客已结束,许多地方说的还是比较简单抽象,望理解。

Forms身份认证的更多相关文章

  1. 细说ASP.NET Forms身份认证

    阅读目录 开始 ASP.NET身份认证基础 ASP.NET身份认证过程 如何实现登录与注销 保护受限制的页面 登录页不能正常显示的问题 认识Forms身份认证 理解Forms身份认证 实现自定义的身份 ...

  2. 简单的ASP.NET Forms身份认证

    读了几篇牛人的此方面的文章,自己也动手做了一下,就想有必要总结一下.当然我的文章质量自然不能与人家相比,只是写给从没有接触过这个知识点的朋友. 网站的身份认证我以前只知道session,偶然发现一些牛 ...

  3. IE11下Forms身份认证无法保存Cookie的问题

    ASP.NET中使用Forms身份认证常见的做法如下: 1. 网站根目录下的Web.config添加authentication节点 <authentication mode="For ...

  4. [转]IE11下Forms身份认证无法保存Cookie的问题

    本文转自:http://www.cnblogs.com/jaxu/p/3698377.html ASP.NET中使用Forms身份认证常见的做法如下: 1. 网站根目录下的Web.config添加au ...

  5. IE11下ASP.NET Forms身份认证无法保存Cookie的问题

    IE11下ASP.NET Forms身份认证无法保存Cookie的问题 折腾了三四天,今天才找到资料,解决了. 以下会转贴,还没来得及深究,先放着,有空再学习下. ASP.NET中使用Forms身份认 ...

  6. 关于Asp.Net Forms身份认证

    Asp.Net管道式的构建个我们提供了通过IHttpMoudle来订阅管线事件来达到干预HTTP请求的目的,Asp.Net的身份认证正是通过此种方式来对请求来执行身份认证的,这篇文章仅仅谈论Forms ...

  7. 权限管理学习 一、ASP.NET Forms身份认证

    说明:本文示例使用的VS2017和MVC5. 系统无论大小.牛逼或屌丝,一般都离不开注册.登录.那么接下来我们就来分析下用户身份认证. 简单实现登录.注销 以前在学习.net的时候不知道什么Forms ...

  8. 【转】权限管理学习 一、ASP.NET Forms身份认证

    [转]权限管理学习 一.ASP.NET Forms身份认证 说明:本文示例使用的VS2017和MVC5. 系统无论大小.牛逼或屌丝,一般都离不开注册.登录.那么接下来我们就来分析下用户身份认证. 简单 ...

  9. ASP.NET Forms身份认证详解

    ASP.NET身份认证基础 在开始今天的内容之前,我想有二个最基础的问题首先要明确: 1. 如何判断当前请求是一个已登录用户发起的? 2. 如何获取当前登录用户的登录名? 在标准的ASP.NET身份认 ...

随机推荐

  1. 【数据库】MySql常用函数梳理

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5866388.html MySql常用函数梳理: 1:数学函数 使用格式:一般用于插入.修改语句中,直接 函数( ...

  2. rqnoj-396-SY学语文-dp

    纯动态规划. 注意初始化为-INF #include<stdio.h> #include<algorithm> #include<iostream> #includ ...

  3. WordPress 主题框架是如何工作的

    主题框架可以说是无比强大的!对于非技术型的 WordPress 用户来说,主题框架使得建立一个独一无二并看起来像是运行一个量身定制的主题的网站成为可能,并且对于 WordPress 开发者来说,它们能 ...

  4. Usage of readonly and const

    Many new learners can not make sure the usage scenarios of readonly and const keywords. In my opinio ...

  5. Debug with jdb

    原文地址: http://www.javaworld.com/article/2077445/testing-debugging/debug-with-jdb.html Q: How do you u ...

  6. Android ViewPager使用具体解释

    这是谷歌官方给我们提供的一个兼容低版本号安卓设备的软件包,里面包囊了仅仅有在安卓3.0以上能够使用的api.而viewpager就是当中之中的一个利用它,我们能够做非常多事情,从最简单的导航,到页面菜 ...

  7. PHP AJAXFORM提交图片上传并显示图片源代码

    PHP dofile.php 文件上传源代码 <? php $file_upload = "upload/"; $file_allow_ext='gif|jpg|jpeg|p ...

  8. QM课程03-采购中的质量管理

    QM模块被包含于采购过程的下列决策制定阶段:查询.供应商选择.采购订单.货物订单.收货.收到检查和收货数量的下达. 供应商下达 质量部门为一种被指定的物料下达一个供应商,它可以限制或限定下达的数量.如 ...

  9. leetcode || 53、Maximum Subarray

    problem: Find the contiguous subarray within an array (containing at least one number) which has the ...

  10. android service总结

    1.通过startservice方法启动一个服务.service不能自己启动自己.若在一个服务中启动一个activity则,必须是申明一个全新的activity任务TASK.通过startservic ...