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日

相关文章

  • Asp.net core 使用SignalR推送消息过程详解

    Asp.net core 使用SignalR推送消息过程详解 SignalR是一个基于ASP.NET Core的实时通讯框架,允许服务器端代码通过WebSockets、Server-Sent Events (SSE)、Long Polling或Forever Frame等协议向客户端推送消息,同时也支持客户端向服务器端发送消息。 SignalR的核心组件是H…

    C# 2023年6月3日
    00
  • .NET几种微服务框架,你用过吗?

    最近有群友问,.NET有哪些微服务框架?.NET的微服务框架还真不多,一般企业都会自己搭建微服务框架,或者基于其它框架搭建微服务(比如abp)。本文将介绍几种微服务框架,供大家学习参考。 一、Service Fabric 简介: Service Fabric 是一个微服务框架,它由微软开发并托管在 Azure 上。它提供了一种分布式系统的方式,允许开发人员在…

    C# 2023年5月11日
    00
  • .Net Core读取文件时中文乱码问题的解决方法分享

    .NET Core读取文件时中文乱码问题的解决方法分享 在使用.NET Core读取含有中文字符的文件时,有时会出现中文字符乱码的问题。这是因为在不同的编码方式下,中文字符会以不同的方式表示。本文将详细介绍读取文件时中文乱码问题的解决方法,并提供两个示例。 问题分析 先来看一个示例: string contents = System.IO.File.Read…

    C# 2023年6月3日
    00
  • c#测试本机sql运算速度的代码示例分享

    我来为你详细讲解如何测试本机 SQL 运算的速度。 一、准备工作 安装 SQL Server 数据库,并创建一个数据库。 安装 Visual Studio 并安装 .NET Core SDK。 在 Visual Studio 中创建一个 .NET Core 控制台应用。 二、测试代码 示例1:插入 1000 条数据并计算耗时 代码如下: using Syst…

    C# 2023年6月1日
    00
  • .NET Core 2.0迁移小技巧之web.config 配置文件示例详解

    首先,我们需要了解什么是“.NET Core”和“web.config”配置文件。”.NET Core” 是一个跨平台的,开源的框架,它使用了不同的部署配置来提高性能。而“web.config”文件是.NET框架中的配置文件,它用于配置ASP.NET应用程序的各个方面,包括Web服务器设置、应用程序设置等。接下来我们会详细讲解如何迁移“.NET Core 2…

    C# 2023年6月3日
    00
  • C#中的Explicit和Implicit详情

    下面是关于“C#中的Explicit和Implicit”的完整攻略。 什么是Explicit和Implicit 在C#中,有两种类型的类型转换:显示类型转换(Explicit)和隐式类型转换(Implicit)。前者需要显式地进行转换,而后者则可以自动进行转换。 为什么需要类型转换呢?因为在编程过程中,有时候需要将一个类型转换为另一个类型,以满足需求或者避免…

    C# 2023年5月15日
    00
  • C# params可变参数的使用注意详析

    C# params 可变参数的使用注意详析 什么是 params? C# 中的 params 关键字可以让我们定义一个可变长度参数列表。使用 params 关键字的方法可以接受零个或多个参数,参数在方法内部被视为数组,可以像普通数组一样进行访问。 使用 params 关键字定义的参数必须是方法的最后一个参数,而且一个方法只能拥有一个 params 关键字定义…

    C# 2023年5月15日
    00
  • .net实现webservice简单实例分享

    关于“.NET实现WebService简单实例分享”的攻略,我将按照以下格式为您进行详细讲解: 1. 什么是Web Service? Web Service是指通过网络对外提供的一组应用程序接口,具有跨平台性、松耦合等特点。通过Web Service,开发人员可以将自己的应用程序接口(API)发布到Internet上,以使得全世界的人都能发现并使用自己的AP…

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