.NET 实现 JWT 登录验证

.NET 实现JWT登录认证

在ASP.NET Core应用程序中,使用JWT进行身份验证和授权已成为一种流行的方式。JWT是一种安全的方式,用于在客户端和服务器之间传输用户信息。

添加NuGet包

首先,我们需要添加一些NuGet包来支持JWT身份验证。在您的ASP.NET Core项目中,打开Startup.cs文件,并在ConfigureServices方法中添加以下代码:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;

注册

// ...

public void ConfigureServices(IServiceCollection services)
{
    // 添加JWT身份验证服务
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        var config = Configuration.GetSection("JwtConfig").Get<JwtConfig>(); // 从appsettings.json读取JwtConfig配置
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = config.Issuer,
            ValidAudience = config.Audience,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.SecretKey))
        };
        
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = async context =>
            {
                var token = context.Request.Cookies["access_token"]; // 从Cookie中获取token值
                if (!string.IsNullOrEmpty(token))
                {
                    context.Token = token; // 将token值设置到JwtBearer上下文中的Token属性
                }
            }
        };
    });

    // ...
}

这里我们使用AddAuthentication方法添加了JWT身份验证服务,并设置了默认的认证方案为JwtBearerDefaults.AuthenticationScheme,这是JWT身份验证的默认方案。

AddJwtBearer方法中,我们通过GetSection方法从appsettings.json文件中读取了一个名为JwtConfig的配置,其中包含了JWT的一些信息,例如签发者(Issuer)、接收者(Audience)、秘钥(SecretKey)等。这些信息将用于验证和生成JWT令牌。

Configure方法中添加JWT认证中间件:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 其他中间件配置...

    app.UseAuthentication();
    app.UseAuthorization();
   //...
}

配置appsettings.json

接下来,我们需要在appsettings.json文件中配置JWT的相关信息。在您的ASP.NET Core项目中,找到appsettings.json文件,并添加以下配置:

{
  // ...
  "JwtConfig": {
    "Issuer": "YourIssuer",
    "Audience": "YourAudience",
    "SecretKey": "YourSecretKey",
    "AccessTokenExpirationMinutes": 60,
    "RefreshTokenExpirationMinutes": 1440
  }
}

您可以根据自己的需求修改配置项的值。这里的AccessTokenExpirationMinutesRefreshTokenExpirationMinutes分别表示访问令牌和刷新令牌的过期时间,单位为分钟。

创建 JWT 设置类

接下来,我们需要创建一个 C# 类来表示 JWT 的配置项,并使用 IOptions 接口将其注入到需要的地方。以下是一个示例的 JwtSettings 类:

csharpCopy codepublic class JwtSettings
{
    public string Issuer { get; set; }
    public string Audience { get; set; }
    public string SecretKey { get; set; }
    public int AccessTokenExpirationMinutes { get; set; }
    public int RefreshTokenExpirationMinutes { get; set; }
}

这个类定义了与 appsettings.json 文件中的配置项相对应的属性。

用户模型

// Models/User.cs

public class UserModel
{
    public string Id { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public string RefreshToken {get; set; }
}

实现JWT登录认证

现在,我们可以开始实现JWT登录认证的逻辑。我们将创建一个JwtService类,用于生成和验证JWT令牌。在您的ASP.NET Core项目中,创建一个名为JwtService.cs的类文件,然后添加以下代码:

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;

public interface IJwtService
{
    string GenerateAccessToken(UserModel user);
    string GenerateRefreshToken();
    bool ValidateAccessToken(string token);
}

public class JwtService : IJwtService
{
    private readonly JwtConfig _jwtConfig;

    public JwtService(IConfiguration configuration)
    {
        _jwtConfig = configuration.GetSection("JwtConfig").Get<JwtSettings>();
    }

    public string GenerateAccessToken(UserModel user)
    {
        // 设置Token的Claims
        List<Claim> claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id),
            new Claim(ClaimTypes.Name, user.Username)
        };

        // 生成Token的密钥
        SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(appSettings.SecretKey));

        // 生成Token的签名证书
        SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);

        // 设置Token的过期时间
        DateTime expires = DateTime.Now.AddMinutes(appSettings.AccessTokenExpirationMinutes);

        // 创建Token
        JwtSecurityToken token = new JwtSecurityToken(
            appSettings.Issuer,
            appSettings.Audience,
            claims,
            expires: expires,
            signingCredentials: creds
        );

        // 生成Token字符串
        string tokenString = new JwtSecurityTokenHandler().WriteToken(token);

        return tokenString;
    }

    public string GenerateRefreshToken()
    {
        var randomNumber = new byte[32];
        using (var rng = new RNGCryptoServiceProvider())
        {
            rng.GetBytes(randomNumber);
            return Convert.ToBase64String(randomNumber);
        }
    }

    public bool ValidateAccessToken(string token)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.UTF8.GetBytes(_jwtConfig.SecretKey);
        try
        {
            tokenHandler.ValidateToken(token, new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = _jwtConfig.Issuer,
                ValidAudience = _jwtConfig.Audience,
                IssuerSigningKey = new SymmetricSecurityKey(key)
            }, out var validatedToken);
        }
        catch (Exception)
        {
            return false;
        }
        return true;
    }
}

这里我们创建了一个JwtService类,实现了IJwtService接口。该服务类通过依赖注入方式注入了IConfiguration,从而可以在构造函数中读取JwtConfig配置。

  • JwtService类中包含了生成访问令牌和刷新令牌的方法,以及验证访问令牌和从访问令牌中获取用户主体的方法。其中,

    • GenerateAccessToken方法使用JwtSecurityTokenHandler来生成访问令牌,并设置了过期时间、签名等参数。

    • GenerateRefreshToken方法生成一个随机的32位Base64编码的字符串作为刷新令牌。

    • ValidateAccessToken方法验证访问令牌和从访问令牌中获取用户主体。它们使用JwtSecurityTokenHandler来验证令牌的签名、过期时间等信息,并返回验证结果或用户主体。

用户信息加密

在JWT中,用户信息是以Claims的形式进行传递的,但默认情况下,这些信息是以明文的形式存储在令牌中的。为了保护用户信息的安全性,我们可以选择对用户信息进行加密。下面是一个简单的示例,演示如何在生成访问令牌时对用户信息进行加密。

public string GenerateAccessToken(UserModel user)
{
    // 设置Token的Claims
    List<Claim> claims = new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, user.Id),
        new Claim(ClaimTypes.Name, user.Username)
    };

    // 生成Token的密钥
    SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(appSettings.SecretKey));

    // 生成Token的签名证书
    SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);

    // 设置Token的过期时间
    DateTime expires = DateTime.Now.AddMinutes(appSettings.AccessTokenExpirationMinutes);

    // 创建Token
    JwtSecurityToken token = new JwtSecurityToken(
        appSettings.Issuer,
        appSettings.Audience,
        claims,
        expires: expires,
        signingCredentials: creds
    );

    // 生成Token字符串
    string tokenString = new JwtSecurityTokenHandler().WriteToken(token);

    return tokenString;
}

在上面的示例中,我们使用了SigningCredentials类来设置加密的参数,包括加密密钥、加密算法等。这样生成的访问令牌在传递用户信息时会进行加密,增加了用户信息的安全性。

用户登录验证

在用户登录时,我们需要对用户提供的用户名和密码进行验证,并生成访问令牌和刷新令牌。下面是一个简单的示例,演示如何在ASP.NET Core中实现用户登录验证,并生成JWT令牌。

[HttpPost("login")]
public IActionResult Login(UserModel model)
{
    // 验证用户名和密码
    var isValidUser = ValidateUser(model.Username, model.Password);

    if (!isValidUser)
    {
        return BadRequest(new { message = "Invalid username or password" });
    }

    // 生成访问令牌
    var accessToken = _jwtService.GenerateAccessToken(model);

    // 生成刷新令牌
    var refreshToken = _jwtService.GenerateRefreshToken();

    // 返回访问令牌和刷新令牌给客户端
    return Ok(new
    {
        access_token = accessToken,
        refresh_token = refreshToken
    });
}

在上面的示例中,我们通过调用_jwtService.GenerateAccessToken_jwtService.GenerateRefreshToken方法来生成访问令牌和刷新令牌,并将刷新令牌保存到数据库或其他持久化存储中,以便后续使用。

刷新令牌

在用户登录后,访问令牌会在一定时间后过期,此时用户需要使用刷新令牌来获取新的访问令牌,而无需重新登录。下面是一个简单的示例,演示如何在ASP.NET Core中实现刷新令牌功能。

[HttpPost("refresh")]
public IActionResult RefreshToken(UserModel model)
{
    // 验证刷新令牌是否有效
    var isValidRefreshToken = ValidateAccessToken(model.RefreshToken);

    if (!isValidRefreshToken)
    {
        return BadRequest(new { message = "Invalid refresh token" });
    }

    // 生成新的访问令牌
    var accessToken = _jwtService.GenerateAccessToken(model);

    // 返回新的访问令牌给客户端
    return Ok(new
    {
        access_token = accessToken
    });
}

在上面的示例中,我们通过调用_jwtService.GenerateAccessToken方法来生成新的访问令牌,并将其返回给客户端。在生成新的访问令牌时,我们可以使用之前保存的用户信息,例如用户名等。

用户登录简单验证

在每次请求时,我们需要对访问令牌进行验证,以确保用户的身份和权限。下面是一个简单的示例,演示如何在ASP.NET Core中实现对访问令牌的简单验证。

[HttpGet("profile")]
[Authorize]
public IActionResult GetUserProfile()
{
    // 获取当前用户的用户名
    var username = ....;

    // 根据用户名从数据库或其他持久化存储中获取用户信息
    var userModel = ......;

    if (userModel == null)
    {
        return NotFound(new { message = "userModel not found" });
    }

    // 返回用户信息给客户端
    return Ok(new
    {
        username = userModel.Username,
        email = userModel.Email
    });
}

在上面的示例中,我们通过添加[Authorize]属性来标记需要验证访问令牌的API端点。当客户端发送请求时,ASP.NET Core会自动验证访问令牌的有效性,并将用户信息存储在UserModel对象中,以便我们在方法内部访问。

总结

本篇博文通过一个简单的案例,介绍了如何使用 C# .NET 实现 JWT 登录验证,并处理用户信息的加密、刷新 Token、各种验证规则等功能。

原文链接:https://www.cnblogs.com/fantasy-ke/p/17320965.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:.NET 实现 JWT 登录验证 - Python技术站

(0)
上一篇 2023年4月22日
下一篇 2023年4月22日

相关文章

  • C# WCF简单入门图文教程(VS2010版)

    C# WCF简单入门图文教程(VS2010版) WCF(Windows Communication Foundation)是一个用于构建分布式应用程序的框架。它提供了一种统一的编程模型,使得开发人员可以使用不同的传输协议和编码方式来实现分布式应用程序。本文将详细讲解如何使用C# WCF进行简单入门,并提供两个示例。 1. 创建WCF服务 首先,我们需要创建一…

    C# 2023年5月15日
    00
  • C#后端接收form-data,创建实体类教程

    下面我会详细讲解“C#后端接收form-data,创建实体类教程”的完整攻略,以及两个示例。 1. 前置知识准备 在开始讲解之前,我们需要了解一些前置知识,包括: C#语言 .NET Framework ASP.NET Core Web应用程序 2. form-data简介 form-data是一种表单数据格式,它适用于包含文件上传的HTML表单。在form…

    C# 2023年5月31日
    00
  • c#生成站点地图(SiteMapPath)文件示例程序

    当我们在建立一个网站时,通常需要建立一个站点地图文件 (SiteMapPath) 来帮助用户更好的理解我们网站的目录结构,帮助用户更好的导航。 下面我将详细讲解如何用 C# 生成站点地图文件,同时提供两个示例程序: 站点地图文件的基础 什么是站点地图文件 站点地图文件是一种可供搜索引擎和网站访问者使用的页面列表,其中包含了站点中的所有页面和与每个页面相关的元…

    C# 2023年6月1日
    00
  • C# WPF上位机实现和下位机TCP通讯的方法

    下面是对于“C# WPF上位机实现和下位机TCP通讯的方法”的完整攻略: 1. 概述 要实现 C# WPF 上位机和下位机(例如单片机)之间的 TCP 通讯,可以分为以下三个步骤:1. 建立 TCP 连接2. 实现数据的发送和接收3. 关闭 TCP 连接 这三个步骤的具体实现细节将在下面讨论,示例将基于 C# 语言和 WPF 框架。 2. 建立 TCP 连接…

    C# 2023年5月15日
    00
  • 使用ASP.NET一般处理程序或WebService返回JSON的实现代码

    使用ASP.NET一般处理程序或WebService返回JSON的实现代码,主要涉及到以下步骤: 1.创建一个类来模拟JSON数据: public class Person { public string Name { get; set; } public int Age { get; set; } public string Gender { get; s…

    C# 2023年5月31日
    00
  • Unity中Instantiate实例化物体卡顿问题的解决

    关于Unity中Instantiate实例化物体卡顿问题的解决,我整理了以下攻略: Unity中Instantiate实例化物体卡顿问题的解决 问题描述 在Unity开发过程中,使用Instantiate()函数实例化物体时,会出现卡顿现象,特别是当要大量实例化物体时,卡顿现象会更加明显。 解决方法 方法一:使用对象池 使用对象池是一种常见的解决Instan…

    C# 2023年6月3日
    00
  • 一文带你快速学会C#中WinForm框架的使用详解

    标题:一文带你快速学会C#中WinForm框架的使用详解 简介 在本文中,我将全面介绍C#中WinForm框架的使用,包括窗体的基本操作、控件的使用、事件的处理等内容。 窗体的基本操作 创建窗体 在C#中创建一个Windows窗体非常简单,只需要借助Visual Studio创建Windows Form应用即可。 窗体属性设置 在Windows窗体中,有很多…

    C# 2023年5月31日
    00
  • 详解ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁

    详解ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁 在ASP.Net Core应用程序中,分布式锁是一项非常重要的任务,它可以帮助您避免并发问题和数据竞争。CSRedis是一种流行的Redis客户端,它可以帮助我们实现分布式锁。在本攻略中,我们将详细讲解如何借助CSRedis实现一个安全高效的分布式锁,并提供两个示例说明。 步骤…

    C# 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部