.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/ke210/archive/2023/04/15/17320965.html

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

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

相关文章

  • 详解如何使用Net将HTML简历导出为PDF格式

    如何使用.NET将HTML简历导出为PDF格式攻略 在本攻略中,我们将深入讲解如何使用.NET将HTML简历导出为PDF格式,并提供两个示例说明。 步骤一:安装NuGet包 在使用.NET将HTML简历导出为PDF格式之前,我们需要安装NuGet包。以下是安装NuGet包的步骤: 在Visual Studio中,打开NuGet包管理器控制台。 运行以下命令:…

    C# 2023年5月17日
    00
  • 详解C#App.config和Web.config加密

    C#中的App.config和Web.config文件是应用程序的配置文件,这些配置文件中可能会包含敏感信息,如连接数据库的密码,这些信息一旦泄露将会造成严重的安全问题。因此,对配置文件的加密是必要的。 以下是对C# App.config和Web.config加密的完整攻略: 步骤1:创建加密命令 使用ASP.NET提供的命令工具aspnet_regiis来…

    C# 2023年5月15日
    00
  • C#中获取文件大小问题

    C#中获取文件大小是一项比较基础的操作,可以通过 System.IO 命名空间下的 FileInfo 类来实现。下面是具体的操作步骤: 引入命名空间 首先,需要在代码文件中引入 System.IO 命名空间,可以使用以下代码: using System.IO; 实例化 FileInfo 对象 在 FileInfo 类中,有一个 Length 属性可以获取文件…

    C# 2023年5月14日
    00
  • ASP.NET(VB)写的后台发送短信实现代码

    下面我就为您详细讲解ASP.NET (VB) 写的后台发送短信实现代码的完整攻略。 第一步:获取短信API 要发送短信,我们需要使用短信API。在国内,可以使用阿里云、腾讯云等云服务商提供的短信API。获取到短信API之后,我们需要在代码中引入相应的SDK,并按照API文档进行配置和调用。 第二步:编写发送短信的代码 实现方式一:使用SDK发送短信 以阿里云…

    C# 2023年5月31日
    00
  • 深入理解c#多态

    深入理解C#多态的完整攻略 什么是多态? 在面向对象编程(OOP)中,多态是指同一个方法在不同情况下表现出现不同的行为。简单来说,就是同样的操作在不同的对象上可以有不同的实现。多态的概念是OOP中的三大特性之一,其它两个是封装和继承。 C#中的多态 C#中的多态性是通过虚方法(Virtual Methods)、抽象类和接口实现的。关键字virtual和ove…

    C# 2023年5月31日
    00
  • C#常用知识点简单回顾(有图有真相)

    “C#常用知识点简单回顾(有图有真相)” 的攻略主要内容包括以下几个方面: 1. C#基础语法回顾 这一部分主要讲解C#的基础语法,并通过代码示例让读者对C#的语法能够有一个初步的认识。具体内容包括以下几个方面: 1.1 基本数据类型 介绍了C#中常见的数据类型,如int,float,double等,并通过代码示例演示了如何使用这些数据类型。 1.2 条件语…

    C# 2023年6月1日
    00
  • C#实现餐饮管理系统完整版

    C#实现餐饮管理系统完整版攻略 1. 需求分析 在开始编写餐饮管理系统前,我们需要对需求进行分析。餐饮管理系统主要包括以下功能: 管理员登陆 菜单管理:添加、修改、删除菜单 前台收银:下单、结算等功能 后厨管理: 查看订单、制作菜品等功能 统计报表:查看销售报表、库存等功能 2. 设计数据库 在设计数据库时,我们可以考虑以下表格: User: 存储管理员信息…

    C# 2023年5月31日
    00
  • C# Path.GetRandomFileName – 获取一个随机文件名

    Path.GetRandomFileName 方法是C#中的一个静态方法,其返回一个随机生成的文件名(不包含路径),该方法的作用是用于生成一个随机的文件名,以避免文件名的冲突问题。 使用该方法非常简单,只需要在代码中调用该静态方法即可,该方法的语法格式如下: public static string GetRandomFileName(); 该方法返回一个字…

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