《ASP.NET Core 与 RESTful API 开发实战》-- (第8章)-- 读书笔记(上)
第 8 章 认证和安全
8.1 认证
认证(Authentication)是指验证用户身份的过程,授权(Authorization)是验证一个已经通过认证的用户是否有权限做某些事的过程
常见的 HTTP 认证方式包括:
- Basic 认证:用户名密码
- Digest 认证:摘要认证
- Bearer 认证:token 认证
常见的 Token 有两种类型,一种是引用类型,另一种是自包含类型。前者是服务器根据自己定义的规则随机生成的字符串,后者是对用户信息以及 Token 元数据等信息进行编码、加密之后得到的结果。JWT 是最为常见的自包含类型的 Token
JWT 全名为 JSON Web Token,是一个开放标准,一种 Token 格式,它由3部分组成,分别是头部、负载和签名,各部分之间以.隔开,例如:header.payload.signature
头部由两部分组成,即 Token 类型和使用的算法名称
{
"alg": "HS256",
"type": "JWT"
}
负载部分包括要传输的信息,通常由多个 Claim 构成,Claim 是与实体相关的信息以及其他元数据
Claim 有3种类型:已注册、公有、私有
公共类型的 Claim 主要是常见且通用的 Claim,如 name、email 和 gender 等
一个典型的 JWT 负载如下:
{
"sub": "1234567890",
"name": "John Doe",
"Admin": true
}
签名部分通过使用头部指定的算法以及一个密钥,对 Base64 编码后的头部和负载加密而成
HMAC-SHA256(
encodeBase64Url(header) + '.' +
encodeBase64Url(payload),
secret)
签名主要用于验证消息不会被篡改
最终,上述3个部分的内容均使用 Base64 编码,并使用 "." 将各部分隔开,即为一个标准的 JWT
使用 JWT 能够以紧凑的方式传递用户信息,并通过签名保护其中的信息不会被修改。需要注意到是,它很容易被解码,因此不应该在 Token 中包含敏感信息,如用户密码等
接下来,通过 JwtBearer 认证中间件实现基于 Token 的认证
添加nuget
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
在 Startup 类中注册服务
// defaultScheme用于指定当未指定具体认证方案时将会使用的默认方案
services.AddAuthentication(defaultScheme: JwtBearerDefaults.AuthenticationScheme);
在 Startup 类中使用服务
app.UseAuthentication();
对于不同的认证方式(如 Cookie 或 JwtBearer),ASP.NET Core 均在其实现的包中包含相应的扩展方法,以便添加相应类型的认证方式,例如
services.AddAuthentication(defaultScheme: JwtBearerDefaults.AuthenticationScheme)
.AddCookie()
.AddJwtBearer();
可以添加多个相同类型的认证方式,但指定的名称必须不同
services.AddAuthentication()
.AddCookie("cookie1")
.AddCookie("cookie2");
当添加 JwtBearer 认证方式时,JwtBearerOptions 对象能够配置该认证的选项,它的 TokenValidationParameters 属性用于指定验证 Token 时的规则
var tokenSection = Configuration.GetSection("Security:Token");
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
ValidIssuer = tokenSection["Issuer"],// 合法的签发者
ValidAudience = tokenSection["Audience"],// 合法的接受方
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenSection["Key"])),// 签名验证的安全密钥
ClockSkew = TimeSpan.Zero// 验证时间的时间偏移值
};
});
上述代码会从配置文件中读取关于 Token 的信息,因此还需要在 appsettings.json 中添加如下内容
"Security": {
"Token": {
"Issuer": "demo_issuer",
"Audience": "demo_audience",
"Key": "<your_secret_key>"
}
},
接下来,为了使用 ASP.NET Core 的认证功能来保护资源,应为 Controller 或 Action 添加 [Authorize] 特性
[Authorize]
public class AuthorController : ControllerBase
{}
如果使用了多个认证方式,可以使用 [Authorize] 特性的 AuthenticationSchemes 属性指明当前使用哪一种认证方式
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class BookController : ControllerBase
{}
JwtBearer 中间件提供了对 JWT 的验证功能,然而并未能提供生成 Token 的功能。要生成 Tokne,可以使用 JwtSecurityTokenHandler 类
接下来,我们创建一个 Controller,它将会根据用户的认证信息生成 JWT,并返回给客户端
namespace Library.API.Controllers
{
[Route("auth")]
[ApiController]
public class AuthenticateController : ControllerBase
{
public IConfiguration Configuration { get; set; }
public AuthenticateController(IConfiguration configuration)
{
Configuration = configuration;
}
[HttpPost("token", Name = nameof(GenerateToken))]
public IActionResult GenerateToken(LoginUser loginUser)
{
if (loginUser.UserName != "demouser" || loginUser.Password != "demopassword")
{
return Unauthorized();
}
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub,loginUser.UserName)
};
var tokenConfigSection = Configuration.GetSection("Security:Token");
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenConfigSection["Key"]));
var signCredential = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var jwtToken = new JwtSecurityToken(
issuer: tokenConfigSection["Issuer"],
audience: tokenConfigSection["Audience"],
claims: claims,
expires: DateTime.Now.AddMinutes(3),// 由于 JWT 不支持销毁以及撤回功能,因此在设置它的有效时间时,应该设置一个较短的时间
signingCredentials: signCredential);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(jwtToken),
expiration = TimeZoneInfo.ConvertTimeFromUtc(jwtToken.ValidTo, TimeZoneInfo.Local)
});
}
}
public class LoginUser
{
public string UserName { get; set; }
public string Password { get; set; }
}
}
对于受保护的资源,应在每一次请求时均携带 Authorization 消息头
如果不希望添加认证功能,则应为其添加 [AllowAnonymous] 特性
当服务器验证 Token 通过时,JwtBearer 认证处理器会通过 JwtSecurityTokenHandler 将 Token 转换为 ClaimPrincipal 对象,并将他赋值给 HttpContext 对象的 User 属性
ClaimPrincipal 类代表一个用户,它包含一些重要的属性(如 Identity 和 Identities),它们分别返回该对象中主要的 ClaimsIdentity 对象和所有的 ClaimsIdentity 对象集合
ClaimsIdentity 类代表用户的一个身份,一个用户可以有一个或多个身份;ClaimsIdentity 类则又由一个或多个 Claim 组成
Claim 类代表与用户相关的具体信息(如用户名和出生日期等)


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
《ASP.NET Core 与 RESTful API 开发实战》-- (第8章)-- 读书笔记(上)的更多相关文章
- 使用ASP.NET Core构建RESTful API的技术指南
译者荐语:利用周末的时间,本人拜读了长沙.NET技术社区翻译的技术标准<微软RESTFul API指南>,打算按照步骤写一个完整的教程,后来无意中看到了这篇文章,与我要写的主题有不少相似之 ...
- 4类Storage方案(AS开发实战第四章学习笔记)
4.1 共享参数SharedPreferences SharedPreferences按照key-value对的方式把数据保存在配置文件中,该配置文件符合XML规范,文件路径是/data/data/应 ...
- 菜单Menu(AS开发实战第四章学习笔记)
4.5 菜单Menu Android的菜单主要分两种,一种是选项菜单OptionMenu,通过按菜单键或点击事件触发,另一种是上下文菜单ContextMenu,通过长按事件触发.页面的布局文件放在re ...
- [Android]《Android艺术开发探索》第一章读书笔记
1. 典型情况下生命周期分析 (1)一般情况下,当当前Activity从不可见重新变为可见状态时,onRestart方法就会被调用. (2)当用户打开新的Activity或者切换到桌面的时候,回调如下 ...
- 温故知新,使用ASP.NET Core创建Web API,永远第一次
ASP.NET Core简介 ASP.NET Core是一个跨平台的高性能开源框架,用于生成启用云且连接Internet的新式应用. 使用ASP.NET Core,您可以: 生成Web应用和服务.物联 ...
- 快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践
本节内容,涉及到6.1-6.6(P155-182),以WebApi说明为主.主要NuGet包:无 一.创建WebApi的最佳实践,综合了RPC和Restful两种风格的特点 1 //定义Person类 ...
- 零基础ASP.NET Core WebAPI团队协作开发
零基础ASP.NET Core WebAPI团队协作开发 相信大家对“前后端分离”和“微服务”这两个词应该是耳熟能详了.网上也有很多介绍这方面的文章,写的都很好.我这里提这个是因为接下来我要分享的内容 ...
- ASP.NET Core WebApi构建API接口服务实战演练
一.ASP.NET Core WebApi课程介绍 人生苦短,我用.NET Core!提到Api接口,一般会想到以前用到的WebService和WCF服务,这三个技术都是用来创建服务接口,只不过Web ...
- 从 0 使用 SpringBoot MyBatis MySQL Redis Elasticsearch打造企业级 RESTful API 项目实战
大家好!这是一门付费视频课程.新课优惠价 699 元,折合每小时 9 元左右,需要朋友的联系爱学啊客服 QQ:3469271680:我们每课程是明码标价的,因为如果售价为现在的 2 倍,然后打 5 折 ...
- Asp.Net Core 5 REST API - Step by Step
翻译自 Mohamad Lawand 2021年1月19日的文章 <Asp.Net Core 5 Rest API Step by Step> [1] 在本文中,我们将创建一个简单的 As ...
随机推荐
- 《3D编程模式》写书-第3次记录
大家好,这段时间我完成了"积木模式"."管道模式"."多线程模式"."依赖隔离模式"的初稿 目前我已经完成了所有模式(7 ...
- 【教你学Qt桌面端开发】pt1:浅谈Qt:特色C++主义类库
还在为头脑简单看不懂代码而发愁吗?还在为思想浅薄只会人云亦云.拾人牙慧.鹦鹉学舌而遭人鄙夷吗? <教你写代码>,从另一维度解读代码,让你成为见解独特的黑马观众. 教你学Qt桌面端开发栏目旨 ...
- python常见面试题讲解(十二)句子逆序
题目描述 将一个英文语句以单词为单位逆序排放.例如"I am a boy",逆序排放后为"boy a am I"所有单词之间用一个空格隔开,语句中除了英文字母外 ...
- 小白学标准库之 log
日常开发中,日志 log 几乎是必不可少.本文旨在介绍 log 的使用和内部实现等. 1. log 使用及实现 package main import ( "fmt" " ...
- 基于java+springboot的宠物商店、宠物管理系统
该系统是基于java+springboot开发的宠物商城,用户可以登录该网站购买宠物.该系统是给师弟开发的课程作业.运行过程中的问题,可以咨询github或留言. 演示地址 前台地址: http:// ...
- NSSCTF Round#11 Basic 密码个人赛复盘
[NSSRound#11 Basic]ez_enc ABAABBBAABABAABBABABAABBABAAAABBABABABAAABAAABBAABBBBABBABBABBABABABAABBAA ...
- [转帖]oceanbase 的简单介绍
English | 中文版 OceanBase Database 是一个分布式关系型数据库.完全由蚂蚁集团自主研发. OceanBase 基于 Paxos 协议以及分布式架构,实现了高可用和线性扩展. ...
- [转帖]为什么不推荐使用/etc/fstab
https://www.jianshu.com/p/af49a5d0553f 对于工作中使用服务器的公司来讲,每到节假日来临时,总免不了对服务器进行下电.而收假回来的早上,则会有一个早上的时间会花费在 ...
- [转帖]缓存与存储的一致性策略:从 CPU 到分布式系统
https://zhuanlan.zhihu.com/p/151745863 在计算机系统设计实践中,我们常常会遇到下图所示架构: 为了解决单个存储器读吞吐无法满足要求的问题,常常需要在存储器上面增加 ...
- [转帖]FIO磁盘性能测试工具
https://www.cnblogs.com/lyhabc/p/16708771.html 简介 一般我们测试硬盘或者存储的性能的时候,会用Linux系统自带的dd命令,因为是自带命令,简单易使用, ...