安装Nuget包

项目中添加包:dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

添加认证配置

Startup类中添加如下配置:

public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthentication(defaultScheme: JwtBearerDefaults.AuthenticationScheme);
} public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

AddAuthentication方法会向依赖注入容器添加认证服务和它所使用的其他服务,其参数defaultScheme用于指定当未指定具体的认证方案时将会使用的默认方案,上例为Bearer认证。

AddAuthentication方法的另一重载能够使用AuthenticationOptions类为认证过程中的每一个动作指明所使用的认证方案,如DefaultAuthenticateScheme、

DefaultChallengeScheme、

DefaultSignInScheme、

DefaultSignOutScheme、

DefaultForbidScheme。

如果没有为这些属性设置认证方案,则将使用DefaultScheme属性所指定的值。

当添加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
};
});

TokenValidationParameters类作为Token验证参数类,它包含了一些属性,这些属性如ValidateAudience、ValidateIssuer、ValidateLifetime和ValidateIssuerSigningKey,它们都是布尔类型,用于指明是否验证相应的项;而ValidIssuer和ValidAudience属性则用于指明合法的签发者(Issuer)与接受方(Audience)。在上例中,它们的值都从配置文件中获取;IssuerSigningKey属性的值用于指定进行签名验证的安全密钥,它的值为SymmetricSecurityKey对象,即对称加密密钥;ClockSkew属性的值表示验证时间的时间偏移值。

上述代码会从配置文件中读取关于Token的信息,因此还需在appsettings.json中添加如下内容。

"Security": {
"Token": {
"Issuer": "demo_issuer",
"Audience": "demo_audience",
"Key": "<your_secret_key>"
}
}

为Controller添加认证

接下来,为了使用ASP.NET Core的认证功能来保护资源,应为Controller或Action添加[Authorize]特性,该特性能够实现在访问相应的Controller或Action时,要求请求方提供指定的认证方式,它位于Microsoft.AspNetCore.Authorization命名空间中。需要为AuthorController和BookController添加该特性。

[Authorize]
public class AuthorController : ControllerBase
{
}
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class BookController : ControllerBase
{
}

如果使用了多个认证方式,则可以使用[Authorize]特性的AuthenticationSchemes属性指明当前Controller或Action要使用哪一种认证方式(如上例中的BookController);如果不设置,则会使用所添加认证时设置的默认方案;如果没有设置默认方案,则会出现InvalidOperationException异常,并提示未指定默认方案;此外,如果为AuthenticationSchemes属性指定了不存在的方案名称,也会出现InvalidOperationException异常。

此时再访问Book和Author资源,会出现401 Unauthorized异常:

如果要允许某个Action可以被匿名访问,可以在Action方法上添加属性标记 [AllowAnonymous]:

[AllowAnonymous]
public async Task<ActionResult<IEnumerable<AuthorDto>>> GetAuthorsAsync([FromQuery] AuthorResourceParameters parameters)

添加认证信息生成接口

JwtBearer中间件提供了对JWT的验证功能,然而并未提供生成Token的功能。要生成Token,可以使用JwtSecurityTokenHandler类,它位于System.IdentityModel.Tokens.Jwt命名空间,它不仅能够生成JWT,由于它实现了ISecurityTokenValidator接口,因此对JWT的验证也是由它完成的。接下来,我们将创建一个Controller,它将会根据用户的认证信息生成JWT,并返回给客户端。

在Controllers文件夹中创建一个Controller,名为AuthenticateController,内容如下:

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens; namespace Library.Api.Controllers
{
[ApiController, Route("api/auth")]
public class AuthenticateController : ControllerBase
{
public IConfiguration Configuration { get; }
public AuthenticateController(IConfiguration configuration)
{
Configuration = configuration;
} [HttpPost("token", Name = nameof(GenerateToken))]
public IActionResult GenerateToken(string username, string password)
{
if (username != "demouser" || password != "demopassword")
{
return Unauthorized();
} var claims = new List<Claim>{
new Claim(JwtRegisteredClaimNames.Sub, 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),
signingCredentials: signCredential
); return Ok(new {
token = new JwtSecurityTokenHandler().WriteToken(jwtToken),
expiration = TimeZoneInfo.ConvertTimeFromUtc(jwtToken.ValidTo, TimeZoneInfo.Local)
});
}
}
}

在AuthenticateController中的GenerateToken方法中,通过创建JwtSecurityToken对象,并使用JwtSecurityTokenHandler对象的WriteToken方法最终得到生成的JWT。当创建JwtSecurityToken对象时,我们可以指定issuer、audience以及当前用户的Claim信息,此外,还可以指定该Token的有效时间。这里需要注意,由于JWT不支持销毁以及撤回功能,因此在设置它的有效时间时,应设置一个较短的时间(如上例中的3分钟),这样可以有效避免Token在意外被窃取后所带来的风险。

现在就可以请求认证接口获取 token:

这时重新请求资源接口,在请求头中添加Authorization项,值为Bearer ,就可以得到结果了:

这次示例中,使用了固定的用户名和密码,实际情况中,用户名和密码通常是存在数据库中的,可以使用ASP.NET Core Identity来实现这一功能。

MVC之实现基于token的认证的更多相关文章

  1. 使用 AngularJS & NodeJS 实现基于token 的认证应用(转)

    认证是任何 web 应用中不可或缺的一部分.在这个教程中,我们会讨论基于 token 的认证系统以及它和传统的登录系统的不同.这篇教程的末尾,你会看到一个使用 AngularJS 和 NodeJS 构 ...

  2. 使用 AngularJS & NodeJS 实现基于 token 的认证应用

      认证是任何Web应用中不可或缺的一部分.在这个教程中,我们会讨论基于token的认证系统以及它和传统的登录系统的不同.这篇教程的末尾,你会看到一个使用 AngularJS 和 NodeJS 构建的 ...

  3. NodeJS 实现基于 token 的认证应用

    此段摘自 http://zhuanlan.zhihu.com/FrontendMagazine/19920223 英文原文 http://code.tutsplus.com/tutorials/tok ...

  4. 基于Token的WEB后台认证机制

    几种常用的认证机制 HTTP Basic Auth HTTP Basic Auth简单点说明就是每次请求API时都提供用户的username和password,简言之,Basic Auth是配合RES ...

  5. Java实现基于token认证

    随着互联网的不断发展,技术的迭代也非常之快.我们的用户认证也从刚开始的用户名密码转变到基于cookie的session认证,然而到了今天,这种认证已经不能满足与我们的业务需求了(分布式,微服务).我们 ...

  6. 【转】基于Token的WEB后台认证机制

    原谅地址:http://www.cnblogs.com/xiekeli/p/5607107.html 几种常用的认证机制 HTTP Basic Auth HTTP Basic Auth简单点说明就是每 ...

  7. JWT(Json web token)认证详解

    JWT(Json web token)认证详解 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该to ...

  8. 基于token的后台身份验证(转载)

    几种常用的认证机制 HTTP Basic Auth HTTP Basic Auth简单点说明就是每次请求API时都提供用户的username和password,简言之,Basic Auth是配合RES ...

  9. 基于token的验证

    认证.权限和限制 身份验证是将传入请求与一组标识凭据(例如请求来自的用户或其签名的令牌)相关联的机制.然后 权限 和 限制 组件决定是否拒绝这个请求. 简单来说就是: 认证确定了你是谁 权限确定你能不 ...

随机推荐

  1. # PyComCAD介绍及开发方法

    项目地址:https://github.com/JohnYang1210/PycomCAD 1.综述 ​ 提到Autocad在工业界的二次开发,VB或者Lisp可能作为常用的传统的编程语言.但是,Py ...

  2. 生产者与消费者以及ActiveMQ

    生产者与消费者以及ActiveMQ 一. 多线程实现生产者与消费者 1.1 生产者与消费者头文件 #pragma once #include <iostream> #include < ...

  3. Django中文文档-模型Models(二):Meta选项、模型属性、模型方法

    元数据(Meta)选项 使用内部的class Meta 定义模型的元数据,例如: from django.db import models class Ox(models.Model): horn_l ...

  4. Spring-04 Bean的自动装配

    Spring-04 Bean的自动装配 Bean的自动装配 1.自动装配说明 自动装配是使用spring满足bean依赖的一种方法. spring会在应用上下文中为某个bean寻找其依赖的bean. ...

  5. js中数据、内存、变量的概念及三者之间的关系

    目录 数据.内存.变量的概念及三者之间的关系 什么是数据 数据的特点 什么是内存 栈内存 堆内存 JS引擎如何管理内存 什么是变量 变量是普通类型时 变量是引用类型时 数据.内存.变量的三者之间的关系 ...

  6. dubbo实战之一:准备和初体验

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. 干货满满-原来这才是hooks-React Hooks使用心得

    序言 ---最后有招聘信息哦-React是一个库,它不是一个框架.用于构建用户界面的Javascript库.这里大家需要认识这一点.react的核心在于它仅仅是考虑了如何将dom节点更快更好更合适的渲 ...

  8. 【粉丝问答10】C语言关键字static的使用详解

    视频地址:https://www.ixigua.com/6935761378816819748 粉丝提问 粉丝问题,总结一下: 关键字static的使用方法. 要想搞清楚关键字static的使用方法, ...

  9. CVE-2020-1938 -Tomcat-AJP任意文件读取/包含

    为什么这个漏洞被称作 Ghostcat(幽灵猫)? 这个漏洞影响全版本默认配置下的 Tomcat(在我们发现此漏洞的时候,确认其影响 Tomcat 9/8/7/6 全版本,而年代过于久远的更早的版本未 ...

  10. 理解函数式编程中的函数组合--Monoids(二)

    使用函数式语言来建立领域模型--类型组合 理解函数式编程语言中的组合--前言(一) 理解函数式编程中的函数组合--Monoids(二) 继上篇文章引出<范畴论>之后,我准备通过几篇文章,来 ...