通过官方的介绍可知,若要本地开始部署搭建一个基于.net core 1.0的Web应用,需要下载dotnet SDK,或在Visual Studio IDE之上安装相关插件以布置开发环境。为了使开发环境最小化,选择安装dotnet SDK。下载地址为:http://asp.net
0x00.新建一个Web应用项目
这里不必赘述,到相应目录中运行命令提示符:dotnet new -t web
。dotnet会非常人性化的携带自己的例程,如果基于微软提供的例程进行开发的话,会提速不少。但在实际应用中却往往用不到这些功能,或者需要定制化的一些功能。认证过程就是一个经常需要定制化的模块。本文仅介绍认证过程的自定义。在代码部署到本地之后,项目的运行需要依赖库,包含但可能不仅局限于依赖库的一些配置需要下载到本地,使用dotnet SDK,在项目根目录(携带有project.json文件的目录,该文件内为描述项目的配置文件)执行命令:dotnet restore
。至此,即可运行Web应用程序,执行命令:dotnet run
。将默认监听5000端口,启动Web服务。如果希望改变默认监听端口,一种解决方案是在Program.cs中的WebHostBuilder()
之后添加中间件: .UseUrls(http://localhost:8080)
即可改变监听的套接字。
关于dotnet的详细应用,可以参考官方API文档:https://docs.microsoft.com/zh-cn/dotnet/articles/core/tools/index
为了便于重新构建,将项目的各个附加项均删减。
只预留HomeController类,及HomeController类下的Index方法(或者应该叫Action?)
0x01.认证流程简析
通过观察发现,.net core使用了两种架构来实现新一代的Web应用框架。
- 管道架构(Pipeline)
- 模块架构(MVC)
管道架构的业务流程描述可以理解为在一个业务管道(可能存在分支,在OWIN中通过Map来实现)中先后分布有过滤节点(以Middleware来实现),一个事物实体从管道的输入端输入,逐个流经过滤节点,在过滤节点中可以对流经的事物实体进行过滤(包括增加、删除、丢弃等等动作)。在Web应用中,流经管道的事物实体为客户端发往服务器端的请求实体。
模块架构,这个名称是自己杜撰得出的,与MVC在所属上有不同,特此标记。核心节点为router,即事物实体侧重携带控制信息(即至少有用于指代资源的名称)首先发往router,router根据控制信息来获得资源地址或资源路由,再转交给相关的业务模块进行执行。在MVC定义中,router的职责由Controller来完成,业务执行由Model来完成。在实际工作中,往往Model指代业务实体,Controller下的具体Action执行业务流程。
以认证与具体的业务分发的角度去考虑,客户端如果登录系统(泛指通过系统认证)后,通常的解决方案是将token携带在Cookie中发往服务器。而流经认证模块之后,认证模块可提取Cookie中的值,映射成为用户标识(在.net core 1.0中以HttpContext.User
为代表)。用户标识所具备的属性用户可自定义(通常为角色,代表却不仅局限于代表用户权限)。而微软所提供的例程及模块便是基于Cookie传递token进行的。
实际情况下,采用Cookie存储token的解决方案通常应用于单纯的网站认证。而存在大量的应用,其存储token并不一定在Cookie中,基于此,开始设计自定义的认证过程。
0x02..net core 1.0的认证过程
将在startup.cs
中的app.UseIdentity()
一句删除,此时HttpContext.User
不代表任何登录用户,并在HomeController.cs
中的Index
方法加上AuthorizeAttribute
特征。运行web应用,访问发现返回404 not found。 应该是.net core 1.0 的安全策略。 若删除掉特征AuthorizeAttribute
后,则可正常访问。
将在startup.cs
中的app.UseIdentity()
删除的地方添加如下一段代码:
app.Use(next => async context => { context.User.AddIdentity(new ClaimsIdentity("a", "b", "c"); return next(context); });
此时,无论哪种用户请求体,只要流经该过滤节点后,均被认证为一个用户。此时,即便是HomeController
类中的Index
方法是否携带有AuthorizeAttribute
。均可访问。
由此观之,只要在具体业务分发前(即代码app.UseMvc()
之前)确认认证,即可真实授权。
0x03.HttpContext.User属性
通过上文即可得知,特征是否起作用就是由HttpContext.User决定的。下文给出MSDN的相关定义:
The User Property provides programmatic access to the properties and methods of the IPrincipal interface.
遂观察IPrincipal接口。
Defines the basic functionality of a principal object.
包含属性Identity
Get the identity of the current principal.
包含方法 IsInRole(String)
Determines whether the current principal belongs to the specified role.
至此可知,router将取出HttpContext.User.Identity,来判断是否存在用户。
上边一段程序我们可以得知,添加用户凭证的方法为HttpContext.User.AddIdentity(ClaimsIdentity)
,ClaimsIdentity
实质上是Claim的一个容器。