C#基于jwt实现分布式登录

C#基于JWT实现分布式登录攻略

概述

JWT (JSON Web Token) 是一种用于在网络应用间传递身份信息的安全加密方式。它不需要在服务端存储token信息,使用时请求时发送jwt,服务端解析jwt和密钥进行验证即可,因此是一种轻量级的协议。在分布式架构下,使用JWT可以方便地实现服务间的身份验证。

本攻略将帮助你使用C#实现基于JWT的分布式登录。

步骤

第一步:安装依赖

JWT需要使用依赖包System.IdentityModel.Tokens.Jwt,使用Nuget进行安装:

Install-Package System.IdentityModel.Tokens.Jwt -Version 5.6.0

第二步:定义用户和用户服务

以下为一个简单的用户模型:

public class User
{
    public string Username { get; set; }
    public string Password { get; set; }
}

以下为一个简单的用户服务模型:

public interface IUserService
{
    User Authenticate(string username, string password);
}

你可以使用任何你喜欢的用户和用户服务模型,下面的示例中我们将使用以上提供的模型。

第三步:定义数据源

在我们的示例中,我们使用了一个静态变量作为我们的数据源,如下所示:

public class UserService : IUserService
{
    // 用于演示的数据源
    private List<User> _users = new List<User>
    {
        new User { Username = "admin", Password = "admin" },
        new User { Username = "test", Password = "test" }
    };

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

        // 用户不存在或密码错误
        if (user == null)
            return null;

        // 验证成功,返回用户信息
        return user;
    }
}

在一个实际的应用中,你需要从数据库或其他数据源中检索并验证用户信息,而不是像本示例那样使用静态变量。

第四步:定义JWT Token以及过期时间

为了加强token的安全性,我们需要定义一个key来验证token的有效性。

在本示例中,假设我们已经定义好了jwt security key:

private readonly byte[] _secretKey = Encoding.UTF8.GetBytes("thisIsMyJwtSecurityKey");

在此之后,我们需要定义JWT Token以及过期时间:

private string GenerateJwtToken(User user)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = _secretKey;

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new Claim[]
        {
            new Claim(JwtRegisteredClaimNames.Sub, user.Username),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
        }),
        Expires = DateTime.UtcNow.AddHours(1),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };

    var token = tokenHandler.CreateToken(tokenDescriptor);

    return tokenHandler.WriteToken(token);
}

在此示例中,我们使用了SymmetricSecurityKeyHmacSha256Signature,但是你也可以使用其他的签名算法。

第五步:登录验证

在我们的用户服务中,我们定义了一个Authenticate方法。我们需要在此方法中完成身份验证并输出JWT Token。

在此之后,每次鉴权时,需要将JWT Token附加在HTTP请求标头上。

以下是详细的代码实现:

public class UserController : ControllerBase
{
    private readonly IUserService _userService;
    private readonly byte[] _secretKey = Encoding.UTF8.GetBytes("thisIsMyJwtSecurityKey");

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

    [HttpPost("login")]
    public IActionResult Login([FromBody] User userParam)
    {
        // 身份验证
        var user = _userService.Authenticate(userParam.Username, userParam.Password);

        if (user == null)
            return BadRequest(new { message = "用户名或密码错误。" });

        // 创建jwt token
        var tokenString = GenerateJwtToken(user);

        return Ok(new { token = tokenString });
    }

    [Authorize]
    [HttpGet("test")]
    public IActionResult Test()
    {
        return Ok("身份验证已通过。");
    }

    // 生成 jwt token
    private string GenerateJwtToken(User user)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = _secretKey;

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new Claim[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, user.Username),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
            }),
            Expires = DateTime.UtcNow.AddHours(1),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };

        var token = tokenHandler.CreateToken(tokenDescriptor);

        return tokenHandler.WriteToken(token);
    }
}

在此示例中,我们定义了一个Login方法和一个Test方法。当用户成功通过Login方法时,将返回JWT Token。此后,我们可以使用Test方法进行身份验证。HTTP请求应该附带一个标头——Authorization: Bearer <token>,其中<token>是在Login方法调用时获取到的JWT Token。

示例1:在ASP.Net Core中使用JWT验证身份

以下是一个具体的ASP.Net Core应用场景,其中代码提供了一个可用的控制器:

public class UserController : ControllerBase
{
    private readonly IConfiguration _configuration;

    public UserController(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    [HttpPost("login")]
    public IActionResult Login([FromBody] User user)
    {
        if (user == null)
        {
            return BadRequest("Invalid client request");
        }

        if (user.Username == "test" && user.Password == "test")
        {
            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SecretKey"]));
            var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);

            var tokeOptions = new JwtSecurityToken(
                issuer: "http://localhost:5000",
                audience: "http://localhost:5000",
                claims: new List<Claim>(),
                expires: DateTime.Now.AddSeconds(30),
                signingCredentials: signinCredentials
            );

            var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions);
            return Ok(new { Token = tokenString });
        }

        return Unauthorized();
    }

    [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        var currentUser = HttpContext.User;

        var result = $"Your id is {id} and you are {currentUser.Identity.Name}.";
        return Ok(result);
    }
}

以上示例中,我们首先定义了一个Login方法,其中完成了用户验证并生成了JWT Token。而对于其他需要身份验证的方法,使用了ASP.Net Core默认的[Authorize]验证。

示例2:在WPF中使用JWT验证身份

以下示例是一个WPF应用中使用JWT进行身份验证的示例。我们使用JWT Token作为HTTP请求标头的Authorization参数。

private void SignInButton_Click(object sender, RoutedEventArgs e)
{
     var client = new WebClient();

    try
    {
        client.Headers.Add("authorization", "Bearer " + GetJwtToken());
        var result = client.DownloadString(_url + "/api/values");

        MessageBox.Show(result, "Success");
    }
    catch (WebException ex)
    {
        MessageBox.Show(ex.Message, "Error");
    }
}

private string GetJwtToken()
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(_secretKey);
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Issuer = "issuer",
        Expires = DateTime.UtcNow.AddHours(_tokenDurationHours),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
                            SecurityAlgorithms.HmacSha256Signature),
    };
    var token = tokenHandler.CreateToken(tokenDescriptor);
    var tokenString = tokenHandler.WriteToken(token);

    return tokenString;
}

结论

通过本攻略,我们学习了C#中基于JWT的分布式登录实现方法。在实际应用中,您可以将各种Web和桌面应用程序连接到您的身份验证服务,以实现高度安全的分布式身份验证。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#基于jwt实现分布式登录 - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • Java中import导入的用法说明

    在Java中,import关键字用于导入其他类或接口的定义,以便在当前类中使用这些定义。本文将详细介绍Java中import导入的用法说明,包括静态导入和通配符导入等。 静态导入 静态导入是一种Java 5引入的新特性,它允许我们在代码中直接使用静态成员,而无需使用类名或接口名来限定。以下是一个简单的静态导入示例代码: import static java.…

    C# 2023年5月15日
    00
  • asp.net Md5的用法小结

    下面是关于 ASP.NET Md5 的用法的完整攻略。 什么是 Md5 Md5 是一种密码(或者叫散列)算法,用来对任意长度的数据进行加密,生成一个唯一的固定长度(128 位)的 Hash 值。因为 Md5 生成的 Hash 值几乎不会重复,因此在密码验证、防篡改等场景中被广泛应用。 Asp.net Md5 的使用方式 Asp.net 提供了 System.…

    C# 2023年5月31日
    00
  • C#中使用Spire.XLS来操作Excel数据的实现

    让我来详细讲解一下“C#中使用Spire.XLS来操作Excel数据的实现”的完整攻略。 一、Spire.XLS简介 Spire.XLS是一个功能强大的.NET组件,能够帮助C#开发者快速创建、读取、修改和保存Microsoft Excel文件。它支持Excel文件的多个版本,包括Excel 97-2003、Excel 2007-2010和Excel 201…

    C# 2023年6月7日
    00
  • 为IObservable实现自己的运算符(详解)

    为IObservable实现自己的运算符是Rx编程中的重要内容,这里我将分享一份详细攻略,供大家参考。 1. 了解Rx编程模型 在进行Rx编程之前,我们需要了解Rx编程模型的基本内容。Rx编程模型是由3个基本概念组成的: Observable 表示一个异步事件序列,观察者可在订阅时接收到它发射的事件。 Observer 表示一个接收Observable发射的…

    C# 2023年5月15日
    00
  • C#中的Linq Intersect与Except方法使用实例

    介绍一下C#中Linq的Intersect与Except方法使用实例的攻略。 Linq Intersect与Except方法简介 在C#的Linq中,Intersect与Except方法都是集合间的操作,用于比较两个集合的内容并获取它们间的交集或差集。 Intersect方法:返回两个集合中都存在的元素 Except方法:返回存在于第一个集合中,但不存在于第…

    C# 2023年6月1日
    00
  • C++联合体转换成C#结构的实现方法

    要将C++联合体转换成C#结构(struct),我们需要遵循以下步骤: 创建一个C#结构来表示C++联合体。这个结构的字段应该对应于联合体的成员变量,且顺序应该相同。例如,假设我们有下面这个C++联合体: union MyUnion { int i; float f; }; 对应的C#结构应该如下所示: [StructLayout(LayoutKind.Ex…

    C# 2023年6月2日
    00
  • 详解c# 接口IDisposable的用法

    详解C# 接口IDisposable的用法 什么是IDisposable接口 IDisposable接口是C#语言中的一种接口,其作用是允许程序员手动释放资源,例如文件句柄、数据库连接、网络连接等非托管资源。在.NET Framework的类库中,许多对象都实现了IDisposable接口,例如FileStream、SqlConnection等。程序员可以通…

    C# 2023年5月31日
    00
  • NET索引器使用方法实例代码

    下面是关于“NET索引器使用方法实例代码”的详细讲解: 什么是.NET索引器? .NET索引器是一种特殊的类成员,它可以让我们像访问数组一样访问类的实例,或者说是将类实例转换成一个类似于数组的结构。 如何定义.NET索引器? 在C#中,可以使用this关键字定义一个索引器,具体语法如下: public class Class { // 自定义索引器 publ…

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