我们现在大多数转向ASP.NET Core来使用开发的团队,应该都不是从0开始搭建系统,而是老的业务系统已经在运行,ASP.NET Core用来开发新模块。那么解决用户认证的问题,成为我们的第一个拦路虎。本文将给大家简单阐述一下认证与授权的基本概念,以及基于ASP.NET Core 中间件实现的认证和改造JwtBearer 认证中间件来实现的认证达到与老系统(主要是token-based认证)的集成。

目录

  • 认证与授权

    • 什么是认证
    • 何谓授权
    • 用Middleware拦截
  • 定制JWT Bearer 认证
    • 更改token来源
    • 更改token验证方式
    • 开始授权

认证与授权

什么是认证?

首先认证并不是登录。认证是一个知道用户是谁的一个过程。我们最早使用的基于Session的认证,拿到用户输入的用户名和密码到数据库里面校验一,看看是否正确,如果是正确的我们就放到session里面。这是一个完成认证的过程,系统现在知道你是我的某一个用户了。

那么何谓授权?

现在用户登录之后我们跳转到了另一个页面,这个页面可能会写一段这样的代码。
if(Session["user"]==null)
{
Response.redirect("/login.aspx")
}
如果用户登录的Session不存在则再跳回到登录页面让用户登录。 检查当前用户有没有某个权限的这个过程叫授权。如果没有怎么办?我们就会跳转用户到一个没有权限的提示页面,或者返回  Forbidden 403 的HTTP 状态码,这是最简单的授权。
 
复杂的授权方式包括对角色,对具体资源访问以及操作的授权,这块我们后面再讲。
 
当我们的ASP.NET Core项目需要与老的项目兼容的时候,就需要兼容老项目的认证方式,比如某种自定义的token(这是之前比较常见的做法)。我们需要在ASP.NET Core中根据当前用户header里面的token来判断是否为一个合法的用户。

用Middleware拦截

第一种简单粗暴的方法即用Middleware来拦截。
 
在ASP.NET Core下,MVC以一个Middleware加入到整个HTTP管道。在此之前还会添加一个Routing的Middleware,注意这里的意思也就是说 Routing不再和ASP.NET MVC一样属于它的一部分。正好相反,在ASP.NET Core里面是有一个MVCRouteHandler被 Routing Middleware 加载出来处理请求。关于路由这块我们后面再说。
 
如果我们要在MVC Middleware执行之请拦截请求只要加一个Middleware在 MVC Middleware或者Routing之前即可。
 
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) => {
if (context.Request.Headers.ContainsKey("token"))
{
var token =
context.Request.Headers["token"].FirstOrDefault();
if (token == "jessetalk.cn")
{
await next();
}
}
context.Response.StatusCode = ;
}); app.UseMvc();
}
上面是我们有简易的方法实现的一个Middleware,被加到了MVC之前。当Request的Headers中没有一个值为“jessetalk.cn” 以及 name为” token”的项的时候,我们就返回401状态,并且不执行后面的处理。(不调用 next方法)
 
但是这种办法相当于一刀切,我们添加的这个Middleware发生在 MVC Middleware之前把所有没有认证信息的请求全部拦截掉了。好处是有节省服务器资源(如果确定是要拦截的就没有必须再经过MVC的一些处理了),坏处是无法实现单个Controller或者Action的灵活配置。

定制JWTBearer Authentication

ASP.NET Core为我们实现了JWTBearer Authentication,关于 JWTBearer Authentication的实现可以参考另外一篇文章《在ASP.NET Core中使用JWTBearer Authentication》。我们今天要做的就是通过定制JWTBearer Authentication来达到让它读取我们自定义的Token并且用我们自己的方式来校验这个Token。有点时代倒退的感觉是不是?

如果在时间和人员都足够的情况下,我们是可能直接整体替换成标准的JWT方案,甚至做到SSO。但是架构是没有止境的,在一定的时间框架下,要做到高效且安全的切换,这不失为一种好办法。

首先我们需要看一下在JWTBearer中默认获取的token是在Authorization的头里,Bearer空格加上token。而如果有不规范的做法,可能是直接在headers里面加了一个token,里面有一个用我们自己的算法生成的token。

更改token的来源

JWTBearer authentication handler提供的Events中有一个OnMessageReceived委托可以让我们从另外的地方读取token。

services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o => {
o.Events = new JwtBearerEvents()
{
OnMessageReceived = context => {
var token = context.Request.Headers["token"];
context.Token = token.FirstOrDefault();
return Task.CompletedTask;
},
};
});

定制token的验证方式

从headers里面拿到token之后,下一步就是要把它的验证算法改成我们自己的。这一步可以通过自定义 ISecurityTokenValidator来实现 。我们在这个Validator里面,校验token生成一个ClaimsPrincipal,这个principal就会被赋值到 HttpContext.User上。

同时我们还根据当前的token添加了一个Role Claim,它的值有user和admin。这个可能用来做基于角色的授权 。

public class MyTokenValidator : ISecurityTokenValidator
{
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
{
validatedToken = null; var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
identity.AddClaim(new Claim("name", "jesse"));
identity.AddClaim(new Claim(ClaimsIdentity.DefaultRoleClaimType, securityToken == "jessetalk.cn" ? "admin" : "user"));
var principal = new ClaimsPrincipal(identity);
return principal;
}
}

注意ClaimsIdentity的AuthenticationScheme一定要与我们在UseAuthentication时设置的名称一样。否则Identity.IsAuthenticated无法正确设置为true,我们的授权就没有办法完成。
有了我们自定义的Validator之后,我们要对JwtBearer进行改造,去掉它默认的Validator,加上我们自己定义的这个。

services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{ o.SecurityTokenValidators.Clear();
o.SecurityTokenValidators.Add(new MyTokenValidator());
});

开始进行授权

为了给大家演示上面的功能,我们新建两个Controller,一个是Admin,另一个是Home。两者都需要用户有token才能正常访问,但是对于Admin我们需要用户具有admin的role才可以,否则会被拒绝返回403。

HomeController.cs

[Authorize]
public class HomeController : Controller
{
public IActionResult Index()
{
return Ok();
}
}

当Headers里面没有token 值的时候,API请求返回 401。

当Headers里面有token值时,API可以被正常访问。

我们又加了一个AdminController,不一样的是这次我们给Authorize加上了Role=”admin”,也就是只有拥有admin的Role才可以访问这个API。

[Authorize(Roles ="admin")]
public class AdminController : Controller
{
public IActionResult Index()
{
return Ok();
}
}

当我们用user的token访问时,我们会得到403。

只有用admin的token,才能正常访问。
 
以是就是基于JWT Authentication来定制的我们自己的认证方案的一个基本思路,主要是实现OnMessageReceived来改造token的来源,以及定义自己的 ISecurityTokenValidator 来实现对token的验证。
本文首发于公众号jessetalk。 如需转载,请保留公众号二维码,谢谢。
 

更多精彩文章:

 
ASP.NET Core依赖注入全知道: https://mp.weixin.qq.com/s/lR9O7bXiI704kSu7bKdLGg
我心中的ASP.NET Core新核心对象之WebHost(一) https://mp.weixin.qq.com/s/4Sm2dxMe_WeVOizhqX4ZdA
极简版ASP .NET Core学习路径  https://mp.weixin.qq.com/s/7oKnYLOrff_FmMLm7thnBg
 

ASP.NET Core集成现有系统认证的更多相关文章

  1. ABP官方文档翻译 6.2.1 ASP.NET Core集成

    ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Acti ...

  2. asp.net core 2.0的认证和授权

    在asp.net core中,微软提供了基于认证(Authentication)和授权(Authorization)的方式,来实现权限管理的,本篇博文,介绍基于固定角色的权限管理和自定义角色权限管理, ...

  3. ASP.NET Core 基于JWT的认证(一)

    ASP.NET Core 基于JWT的认证(一) Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计 ...

  4. 【转载】asp.net core 2.0的认证和授权

    在asp.net core中,微软提供了基于认证(Authentication)和授权(Authorization)的方式,来实现权限管理的,本篇博文,介绍基于固定角色的权限管理和自定义角色权限管理, ...

  5. asp.net core集成CAP(分布式事务总线)

    一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET Core 事件总线,分布式事务解决方案:CAP 以及 如何在你的项目中集成 CAP[手把手视频教程],之前也在工作中遇到分布式 ...

  6. asp.net core 集成JWT(一)

    [什么是JWT] JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io/ 通俗地来讲,JWT是能代表用户身份的令牌,可以使用JWT ...

  7. asp.net core 集成JWT(二)token的强制失效,基于策略模式细化api权限

    [前言] 上一篇我们介绍了什么是JWT,以及如何在asp.net core api项目中集成JWT权限认证.传送门:https://www.cnblogs.com/7tiny/p/11012035.h ...

  8. 采用最简单的方式在ASP.NET Core应用中实现认证、登录和注销

    在安全领域,认证和授权是两个重要的主题.认证是安全体系的第一道屏障,是守护整个应用或者服务的第一道大门.当访问者请求进入的时候,认证体系通过验证对方的提供凭证确定其真实身份.认证体系只有在证实了访问者 ...

  9. asp.net core 集成 Prometheus

    asp.net core 集成 prometheus Intro Prometheus 是一个开源的现代化,云原生的系统监控框架,并且可以轻松的集成 PushGateway, AlertManager ...

随机推荐

  1. hdu4686 Arc of Dream 2013 Multi-University Training Contest 9矩阵快速幂

    Arc of Dream Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Tot ...

  2. Hadoop就是一个别人造好的轮子

    这个想法源自于我看了<Hadoop: The Definitive Guide>的Part I Ch 2中MapReduce的引入和介绍,书中先说了怎么通过原始的办法处理数据,然后引入到如 ...

  3. ASP.NET没有魔法——ASP.NET MVC 与数据库之Entity Framework Migrations

    在开发数据库应用程序的时候,经常会遇到某些表需要添加字段或者修改类型.新增表等需求,而对于EF Code First来说关注的只有实体类,当需求变更时只需要添加新的实体类或者在实体类中添加.删除.修改 ...

  4. jdbc学习笔记

    知识概要: 1.JDBC简介 2.JDBC的编码步骤 3.JDBC中常用接口或类详解 4.JDBC中释放资源 5.JDBC进行CRUD 1.JDBC简介 JDBC:Java DataBase Conn ...

  5. c语言构造类型之数组_01

    构造类型--constructed type.至于定义,笔者就省略了,有兴趣的同学可以百度搜索https://www.baidu.com/.今天我们要说的是c语言中最简单的构造类型--数组(array ...

  6. Ubuntu下使用网易云音乐

    Ubuntu15真心各种崩溃啊 最后决定还是换成ubuntu14.04LTS了 在win.android平台上网易云音乐好用到爆 ubuntu下没有网易云音乐的客户端怎么能行 https://gith ...

  7. [mysql使用(3)] 使用mysql的时候遇到的一些错误

    1.Err1055,出现这个问题往往是在执行sql语句时候,在最后一行会出现这个问题. [Err] 1055 - Expression #1 of ORDER BY clause is not in ...

  8. Mybatis基本用法--上

    Mybatis基本用法--上 本文只是为自己查漏补缺.全面的请看官方文档,支持中英文 原理参考:http://blog.csdn.net/luanlouis/article/details/40422 ...

  9. 数据库.MongoDB.安装MongoDB数据库

    树莓派安装方法 版本: mongodb 2.4.10 sudo apt-get install mongodb -y 安装完成后,检查命令 mongo 看到下图的内容,表示已安装并启动成功 ===== ...

  10. jQuery+Ajax+PHP实现异步分页数据显示

    这几天做毕业设计的时候需要使用到一个异步分页的功能,即翻页的时候只是刷新分页的数据而不是刷新整个页面.因为之前做项目的时候没有做过这方面的功能,所以还是纠结了挺长时间的,在网上也找了很多资料,结合自己 ...