1. 首页
  2. IT江湖

ASP.NET Core 2.1 – web api的JWT身份认证教程

使用ASP.NET Core 2.1构建的教程

在本教程中,我们将通过一个简单的示例来说明如何使用C#在ASP.NET Core 2.1 API中实现JWT(JSON Web令牌)身份验证。

示例API只有两个端点/路由,用于演示使用JWT进行身份验证以及使用JWT访问受限路由:

  • /authenticate – 接受包含正文中的用户名和密码的HTTP POST请求的公共路由。如果用户名和密码正确,则返回JWT身份验证令牌和用户详细信息。
  • / – 接受HTTP GET请求的安全路由,如果HTTP Authorization标头包含有效的JWT令牌,则返回应用程序中所有用户的列表。如果没有身份验证令牌或令牌无效,则返回401 Unauthorized响应。

该教程项目可在GitHub上获得,网址为  https://github.com/cornflourblue/aspnet-core-jwt-authentication-api。

在本地运行ASP.NET Core 2.1 JWT示例所需的工具

要在本地开发和运行ASP.NET Core应用程序,请下载并安装以下内容:

  • .NET Core SDK  – 包括.NET Core运行时和命令行工具
  • Visual Studio Code  – 在Windows,Mac和Linux上运行的代码编辑器
  • Visual Studio Code的C#扩展 – 添加了对VS Code的支持,用于开发.NET Core应用程序

在本地运行ASP.NET Core JWT Authentication API

  1. 从https://github.com/cornflourblue/aspnet-core-jwt-authentication-api下载或克隆教程项目代码
  2. 通过dotnet run从项目根文件夹(WebApi.csproj文件所在的位置)的命令行运行来启动API ,您应该看到该消息Now listening on: http://localhost:4000。您可以使用Postman等应用程序直接测试api,也可以使用下面的单页应用程序对其进行测试。

注意:您也可以在VS Code中以调试模式启动应用程序,方法是在VS Code中打开项目根文件夹,然后按F5或从顶部菜单中选择Debug – > Start Debugging。在调试模式下运行允许您附加断点以暂停执行并逐步执行应用程序代码。

使用ASP.NET Core JWT Auth API运行Angular 6客户端应用程序

有关示例Angular 6应用程序的完整详细信息,请参阅Angular 6 – JWT身份验证示例和教程。但要快速启动并运行,请按照以下步骤操作。

  1. 从https://github.com/cornflourblue/angular-6-jwt-authentication-example下载或克隆Angular 6教程代码
  2. 通过npm install从项目根文件夹(package.json所在的位置)中的命令行运行来安装所有必需的npm软件包。
  3. 删除或注释掉在注释下的线// provider used to create fake backend位于中/src/app/app.module.ts的文件。
  4. 通过npm start从项目根文件夹中的命令行运行来启动应用程序,这将启动一个显示Angular示例应用程序的浏览器,它应该与您已经运行的ASP.NET Core JWT Auth API连接。

使用ASP.NET Core JWT Auth API运行React客户端应用程序

有关示例React应用程序的完整详细信息,请参阅React + Redux – JWT身份验证教程和示例。但要快速启动并运行,请按照以下步骤操作。

  1. 从https://github.com/cornflourblue/react-redux-jwt-authentication-example下载或克隆React教程代码
  2. 通过npm install从项目根文件夹(package.json所在的位置)中的命令行运行来安装所有必需的npm软件包。
  3. 删除或注释掉两行的注释下// setup fake backend位于中/src/index.jsx的文件。
  4. 通过npm start从项目根文件夹中的命令行运行来启动应用程序,这将启动一个显示React示例应用程序的浏览器,它应该与您已经运行的ASP.NET Core JWT Auth API连接。

使用ASP.NET Core JWT Auth API运行VueJS客户端应用程序

有关示例VueJS JWT应用程序的完整详细信息,请参阅文章Vue.js + Vuex – JWT身份验证教程和示例。但要快速启动并运行,请按照以下步骤操作。

  1. 从https://github.com/cornflourblue/vue-vuex-jwt-authentication-example下载或克隆VueJS教程代码
  2. 通过npm install从项目根文件夹(package.json所在的位置)中的命令行运行来安装所有必需的npm软件包。
  3. 删除或注释掉两行的注释下// setup fake backend位于中/src/index.js的文件。
  4. 通过npm start从项目根文件夹中的命令行运行来启动应用程序,这将启动一个显示VueJS示例应用程序的浏览器,它应该与您已经运行的ASP.NET Core JWT Auth API连接。

ASP.NET核心JWT认证项目结构

教程项目分为以下文件夹:
控制器 – 定义web api的端点/路由,控制器是通过http请求从客户端应用程序进入web api的入口点。
服务 – 包含业务逻辑,验证和数据访问代码。
实体 – 代表应用程序数据。
助手 – 任何不适合上述文件夹的东西。

单击以下任一链接以跳转到每个文件的描述及其代码:

  • 控制器
    • UsersController.cs
  • 实体
    • User.cs
  • 助手
    • AppSettings.cs
  • 服务
    • UserService.cs
  • appsettings.Development.json
  • appsettings.json
  • Program.cs中
  • Startup.cs
  • WebApi.csproj

ASP.NET核心JWT用户控制器

路径:/Controllers/UsersController.cs

ASP.NET核心用户控制器定义和处理与用户相关的api的所有路由/端点,包括身份验证和标准CRUD操作。在每个路由中,控制器调用用户服务来执行所需的操作,这使控制器能够保持“精益”并完全与业务逻辑和数据访问代码分离。

使用[Authorize]属性使用JWT保护控制器操作,但Authenticate方法除外,该方法允许通过操作方法上的[AllowAnonymous]属性覆盖控制器上的[Authorize]属性来进行公共访问。我之所以选择这种方法,那么除非明确公开,否则添加到控制器的任何新动作方法都是默认的。

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using WebApi.Services;
using WebApi.Entities;

namespace WebApi.Controllers
{
  [Authorize]
    [ApiController]
    [Route("[controller]")]
    public class UsersController : ControllerBase
    {
        private IUserService _userService;

        public UsersController(IUserService userService)
        {
            _userService = userService;
        }

        [AllowAnonymous]
        [HttpPost("authenticate")]
        public IActionResult Authenticate([FromBody]User userParam)
        {
            var user = _userService.Authenticate(userParam.Username, userParam.Password);

            if (user == null)
                return BadRequest(new { message = "Username or password is incorrect" });

            return Ok(user);
        }

        [HttpGet]
        public IActionResult GetAll()
        {
            var users =  _userService.GetAll();
            return Ok(users);
        }
    }
}

ASP.NET核心JWT用户实体

路径:/Entities/User.cs

用户实体类表示应用程序中用户的数据。实体类用于在应用程序的不同部分之间传递数据(例如,在服务和控制器之间),并且可以用于从控制器动作方法返回http响应数据。

namespace WebApi.Entities
{
    public class User
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public string Token { get; set; }
    }
}

ASP.NET核心JWT应用程序设置

路径:/Helpers/AppSettings.cs

app设置类包含appsettings.json文件中定义的属性,用于通过使用内置依赖注入的ASP.NET Core注入类的对象访问应用程序设置。例如,用户服务通过IOptions<AppSettings> appSettings注入构造函数的对象访问应用程序设置。

将配置节映射到类是在ConfigureServicesStartup.cs文件的方法中完成的。

namespace WebApi.Helpers
{
    public class AppSettings
    {
        public string Secret { get; set; }
    }
}

ASP.NET核心JWT用户服务

路径:/Services/UserService.cs

用户服务包含用于验证用户凭证和返回JWT令牌的方法,以及用于获取应用程序中的所有用户的方法。

我在示例中对用户数组进行了硬编码以使其专注于JWT身份验证,在生产应用程序中,建议将用户记录存储在具有散列密码的数据库中。有关包含对用户注册的支持以及使用Entity Framework Core存储数据的扩展示例,请查看ASP.NET Core 2.1 – 用于身份验证,注册和用户管理的简单API

该文件的顶部包含一个定义用户服务的接口,下面是实现该接口的具体用户服务类。

在成功验证后,Authenticate方法使用生成令牌的JwtSecurityTokenHandler类生成JWT(JSON Web令牌),该令牌使用存储在appsettings.json中的密钥进行数字签名。JWT令牌返回给客户端应用程序,然后客户端应用程序必须将其包含在后续Web api请求进行身份验证的HTTP Authorization标头中。

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using WebApi.Entities;
using WebApi.Helpers;

namespace WebApi.Services
{
    public interface IUserService
    {
        User Authenticate(string username, string password);
        IEnumerable<User> GetAll();
    }

    public class UserService : IUserService
    {
        // users hardcoded for simplicity, store in a db with hashed passwords in production applications
        private List<User> _users = new List<User>
        { 
            new User { Id = 1, FirstName = "Test", LastName = "User", Username = "test", Password = "test" } 
        };

        private readonly AppSettings _appSettings;

        public UserService(IOptions<AppSettings> appSettings)
        {
            _appSettings = appSettings.Value;
        }

        public User Authenticate(string username, string password)
        {
            var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);

            // return null if user not found
            if (user == null)
                return null;

            // authentication successful so generate jwt token
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[] 
                {
                    new Claim(ClaimTypes.Name, user.Id.ToString())
                }),
                Expires = DateTime.UtcNow.AddDays(7),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescriptor);
            user.Token = tokenHandler.WriteToken(token);

            // remove password before returning
            user.Password = null;

            return user;
        }

        public IEnumerable<User> GetAll()
        {
            // return users without passwords
            return _users.Select(x => {
                x.Password = null;
                return x;
            });
        }
    }
}

ASP.NET核心JWT应用程序设置(开发)

路径:/appsettings.Development.json

具有特定于开发环境的应用程序设置的配置文件。

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

ASP.NET核心JWT应用程序设置

路径:/appsettings.json

包含所有环境的应用程序设置的根配置文件。

重要信息:"Secret"api使用该属性来签署和验证JWT令牌以进行身份​​验证,使用您自己的随机字符串更新它以确保没有其他人可以生成JWT以获得对您的应用程序的未授权访问。

{
  "AppSettings": {
    "Secret": "THIS IS USED TO SIGN AND VERIFY JWT TOKENS, REPLACE IT WITH YOUR OWN SECRET, IT CAN BE ANY STRING"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

ASP.NET核心JWT程序

路径:/Program.cs

程序类是一个控制台应用程序,它是启动应用程序的主要入口点,它使用实例配置和启动web api主机和Web服务器WebHostBuilder。ASP.NET Core应用程序需要在其中执行的主机。

Kestrel是示例中使用的Web服务器,它是ASP.NET Core的一个新的跨平台Web服务器,默认情况下包含在新项目模板中。Kestrel可以自己用于内部应用程序和开发,但对于面向公众的网站和应用程序,它应该位于更成熟的反向代理服务器(IIS,Apache,Nginx等)后面,它将从Internet接收HTTP请求并转发它们在初步处理和安全检查后到Kestrel。

using System.IO;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace WebApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseUrls("http://localhost:4000")
                .Build();
    }
}

ASP.NET核心JWT启动

路径:/Startup.cs

启动类配置应用程序的请求管道以及如何处理所有请求。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using WebApi.Helpers;
using WebApi.Services;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;

namespace WebApi
{
  public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors();
            services.AddMvc();

            // configure strongly typed settings objects
            var appSettingsSection = Configuration.GetSection("AppSettings");
            services.Configure<AppSettings>(appSettingsSection);

            // configure jwt authentication
            var appSettings = appSettingsSection.Get<AppSettings>();
            var key = Encoding.ASCII.GetBytes(appSettings.Secret);
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            });

            // configure DI for application services
            services.AddScoped<IUserService, UserService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            // global cors policy
            app.UseCors(x => x
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());

            app.UseAuthentication();
            
            app.UseMvc();
        }
    }
}

ASP.NET Core JWT Web Api csproj

路径:/WebApi.csproj

csproj(C#项目)是一个基于MSBuild的文件,它包含应用程序的目标框架和NuGet包依赖性信息。

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>

原创文章,作者:江小编,如若转载,请注明出处:https://jhrs.com/2018/26190.html

发表评论

登录后才能评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

联系我们

QQ:1768281975

在线咨询:点击这里给我发消息

电子邮件:[email protected]

QR code