.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#区分中英文按照指定长度截取字符串的方法

    下面是详细讲解 C# 区分中英文按照指定长度截取字符串的方法的完整攻略。 问题描述 在 C# 中截取字符串时,常常会遇到区分中英文的情况,因为中文字符和英文字符所占的字节大小不同,所以需要按照不同的规则进行截取。具体而言,我们需要实现这样一个功能:给定一个字符串,按照指定的长度截取,如果截取的位置恰好是中文字符,需要往前或往后截取到整个中文字符。 解决方案 …

    C# 2023年6月8日
    00
  • C#利用时间和随即字符串创建唯一的订单编号

    创建唯一的订单编号通常需要使用时间戳和随机字符串,这种方式可以避免重复订单的产生。下面我们来讲解一下如何利用C#实现这种方法。 利用时间戳生成订单编号 时间戳是指从1970年1月1日00时00分00秒到现在的总秒数。我们可以将当前时间转换为时间戳,并将时间戳作为订单编号的一部分,从而保证每个订单编号都是唯一的。 下面是一个示例代码: // 获取当前时间的时间…

    C# 2023年6月1日
    00
  • asp.net javascript 文件无刷新上传实例代码第2/2页

    首先我们需要明确一下本文的主题,它是关于使用ASP.NET框架和JavaScript技术来实现无刷新上传文件功能的攻略。接下来,我会详细讲解这个实例代码的代码结构和实现过程,并附加两个示例说明。 一、代码结构 这个实例由两个部分组成: Default.aspx:这个页面包含一个表单和一些JavaScript代码。 UploadFile.ashx: 这个处理程…

    C# 2023年5月31日
    00
  • C#并行编程之Task任务

    C#并行编程之Task任务 在C#中,任务(Task)是一种表示异步操作的对象,它可以在完成时返回一个结果,也可以不返回任何东西。任务可以被链接在一起,创建任务分组,以及异步等待多个任务的完成。 创建任务 在C#中,我们可以使用Task类创建异步任务。Task类有很多不同的构造函数,其中最常用的是接受一个Action委托的构造函数,如下所示: Task ta…

    C# 2023年5月15日
    00
  • c#.net全站防止SQL注入类的代码

    下面我将详细讲解如何编写一份C#.NET全站防止SQL注入类的代码。 为什么需要防止SQL注入 SQL注入是一种常见的网络攻击方法,攻击者利用特定的技术,向Web应用程序的后端数据库发送恶意SQL查询。这些查询可以导致数据库泄露数据、破坏数据库的结构等等,对网站的安全造成威胁。 因此,保护Web应用程序免受SQL注入攻击非常重要,而采用防止SQL注入的代码类…

    C# 2023年5月31日
    00
  • Linq两个List集合取交集的实现

    为了实现两个List集合的交集,我们可以使用Linq中提供的Intersect方法。这个方法会返回两个集合中共有的元素,而且仅会返回一次(即不会有重复元素)。下面是具体的实现步骤: 1. 引入命名空间 首先要引入System.Linq这个命名空间,因为Linq是其中的一部分: using System.Linq; 2. 创建两个List集合 假设我们要比较的…

    C# 2023年6月1日
    00
  • C#窗体编程(windows forms)禁止窗口最大化的方法

    要禁止C#窗体编程中窗口最大化,可以通过以下方法实现: 1.设置窗口的MaximizeBox属性为false 通过在窗体类的InitializeComponent()方法中或者在窗体类构造函数中设置窗口的MaximizeBox属性为false,即可禁用窗口最大化功能。示例代码如下: public Form1() { InitializeComponent()…

    C# 2023年6月6日
    00
  • C#实现根据银行卡卡号判断银行名

    C#实现根据银行卡卡号判断银行名的方法可以分为以下几个步骤: 步骤一:了解银行卡卡号规则 在判断银行名之前,我们需要了解银行卡卡号的规则,常见银行卡卡号长度如下: 中国银行:19位 工商银行:16位或19位 农业银行:19位 建设银行:19位 交通银行:16位或19位 中信银行:16位或19位 招商银行:16位或19位 浦发银行:16位或19位 兴业银行:1…

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