JWT认证服务

JSON Web Token(JWT)是一种用于在网络应用间安全地传递信息的紧凑、自包含的方式。以下是关于 JWT 认证服务器更详细的介绍,包括其意义、作用、工作原理、组成部分、时效性相关内容、搭建条件以及代码案例。

JWT 的意义与作用

  • 意义:在分布式系统和前后端分离的架构中,JWT 提供了一种安全、便捷的身份验证和授权机制,使得不同的服务和应用之间能够可靠地识别用户身份和权限信息,同时保证信息的安全性和完整性。
  • 作用
    • 身份验证:用户登录后,服务器生成 JWT 并返回给客户端。客户端在后续请求中携带 JWT,服务器通过验证 JWT 来确定用户的身份,判断用户是否有权访问受保护的资源。
    • 授权:JWT 中可以包含用户的角色、权限等信息,服务器根据这些信息来授权用户对不同资源的访问权限,实现细粒度的访问控制。
    • 信息传递:可以在 JWT 中携带一些用户相关的信息,如用户名、用户 ID 等,这些信息可以在不同的服务之间传递,避免了多次查询数据库来获取用户信息,提高了系统的性能和效率。

JWT 的工作原理

  1. 用户登录:用户在客户端输入用户名和密码等登录信息,发送登录请求到服务器。
  2. 服务器验证:服务器接收到登录请求后,对用户提交的信息进行验证。如果验证通过,服务器根据用户信息生成 JWT。
  3. 生成 JWT:JWT 由三部分组成,分别是 Header(头部)、Payload(负载)和 Signature(签名)。服务器将用户的相关信息(如用户 ID、角色、权限等)放入 Payload 中,并使用密钥对 Header 和 Payload 进行签名,生成 Signature。然后将这三部分用点号(.)连接起来,形成一个完整的 JWT 字符串。
  4. 返回 JWT:服务器将生成的 JWT 作为响应返回给客户端。
  5. 客户端存储和使用 :客户端收到 JWT 后,通常会将其存储在本地(如浏览器的 Local Storage 或 Session Storage 中)。在后续的请求中,客户端会在请求头的Authorization字段中携带 JWT,将其发送给服务器。
  6. 服务器验证:服务器接收到带有 JWT 的请求后,会从请求头中提取出 JWT,并使用与生成 JWT 时相同的密钥对其进行验证。验证过程包括验证 Signature 的有效性,以及检查 Payload 中的信息是否符合要求,如用户是否有权访问请求的资源、JWT 是否过期等。如果验证通过,服务器就会处理请求,并返回相应的结果;如果验证失败,服务器则返回错误信息,拒绝处理请求。

JWT 的组成部分

  • Header(头部) :通常包含两部分信息,一是声明类型,即JWT;二是使用的签名算法,如HS256(HMAC with SHA-256)、RS256(RSA with SHA-256)等。例如:

json

复制代码
{
  "alg": "HS256",
  "typ": "JWT"
}
  • Payload(负载) :包含了实际的用户信息和其他相关数据,也被称为声明(Claims)。这些声明可以是标准的声明,如iss(发行人)、exp(过期时间)、sub(主题)等,也可以是自定义的声明,用于存储用户的特定信息,如用户 ID、用户名、角色等。例如:

json

复制代码
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "exp": 1693200000
}

其中,exp字段表示 JWT 的过期时间,是一个 Unix 时间戳,代表从 1970 年 1 月 1 日 00:00:00 UTC 到指定时间的秒数。通过这个字段,服务器可以验证 JWT 是否已经过期,从而判断用户的登录状态是否有效。

  • Signature(签名) :用于验证 JWT 的完整性和真实性。它是通过使用服务器端的密钥对 Header 和 Payload 进行签名生成的。签名的目的是确保 JWT 在传输过程中没有被篡改,并且只有拥有正确密钥的服务器才能生成有效的签名。签名的计算方式取决于在 Header 中指定的签名算法。例如,使用HS256算法时,签名的计算方式如下:

plaintext

复制代码
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secretKey
)

其中,secretKey是服务器端保存的密钥,只有服务器知道这个密钥。通过这个签名,服务器可以验证接收到的 JWT 是否是由自己生成的,并且在传输过程中没有被篡改。

JWT 的时效性

  • 时效性的实现 :如上述 Payload 中的exp字段所示,JWT 通过设置过期时间来控制其时效性。当服务器生成 JWT 时,会根据业务需求设置一个合理的过期时间,并将其放入exp字段中。
  • 时效性的验证 :服务器在接收到 JWT 后,会首先检查exp字段的值。服务器将当前时间与exp字段中的时间进行比较,如果当前时间超过了exp字段中的时间,那么服务器就会认为 JWT 已经过期,拒绝处理该请求,并返回相应的错误信息。例如,在.NET 中,可以使用以下代码来验证 JWT 的时效性:

csharp

复制代码
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;

public class JwtTokenValidator
{
    public bool ValidateToken(string token, string secretKey)
    {
        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(secretKey);
            tokenHandler.ValidateToken(token, new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false,
                ClockSkew = TimeSpan.Zero // 不允许有时间偏移
            }, out SecurityToken validatedToken);

            var jwtToken = (JwtSecurityToken)validatedToken;
            // 检查令牌是否过期
            if (jwtToken.ValidTo < DateTime.UtcNow)
            {
                return false;
            }

            return true;
        }
        catch
        {
            return false;
        }
    }
}

在上述代码中,ValidateToken方法首先使用JwtSecurityTokenHandler来验证 JWT 的签名和有效性,然后检查ValidTo属性(对应于 JWT 中的exp字段)是否大于当前的 UTC 时间。如果ValidTo小于当前时间,说明 JWT 已经过期,返回false;否则,返回true

搭建 JWT 认证服务器的条件

  • 开发环境 :需要安装相应的开发工具和框架,如在.NET 中,需要安装.NET SDK 和相关的 Web 开发框架(如ASP.NET Core);在前端 Vue3 项目中,需要安装 Node.js 和 Vue CLI 等。
  • 密钥管理:服务器需要生成并安全地保存用于签名和验证 JWT 的密钥。这个密钥必须保密,不能泄露给客户端或其他未经授权的方。密钥的长度和强度应根据具体的安全需求来确定,一般来说,使用足够长度的随机字符串作为密钥可以提供较好的安全性。
  • 身份验证逻辑:需要实现用户登录和身份验证的逻辑,包括与数据库或其他身份验证源进行交互,验证用户提供的用户名和密码等信息的正确性。在用户登录成功后,根据用户信息生成 JWT。
  • 路由和中间件配置 :在服务器端,需要配置路由来处理登录请求和受保护资源的请求。同时,需要使用中间件来验证 JWT,确保只有经过身份验证和授权的用户才能访问受保护的资源。在.NETASP.NET Core 中,可以使用JwtBearer中间件来实现 JWT 的验证和授权功能。

代码案例

下面是一个简单的.NET + Vue3 的 JWT 认证服务器代码案例。

  • .NET 后端(ASP.NET Core)
    • 创建项目 :使用dotnet new webapi命令创建一个新的ASP.NET Core Web API 项目。
    • 安装依赖 :安装Microsoft.AspNetCore.Authentication.JwtBearerMicrosoft.IdentityModel.Tokens包,用于 JWT 的生成和验证。
    • 配置 JWT 服务 :在Startup.cs文件中,配置 JWT 服务和身份验证中间件。

csharp

复制代码
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        // 配置JWT认证
        var secretKey = Configuration["Jwt:SecretKey"];
        var key = Encoding.ASCII.GetBytes(secretKey);
        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(x =>
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });

        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}
  • 创建登录接口 :创建一个AuthController,用于处理用户登录请求并生成 JWT。

csharp

复制代码
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;

[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
    private readonly IConfiguration _configuration;

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

    [HttpPost("login")]
    public IActionResult Login([FromBody] UserCredentials credentials)
    {
        // 这里可以与数据库或其他身份验证源进行交互,验证用户凭据
        if (credentials.Username == "admin" && credentials.Password == "123456")
        {
            // 创建Claims
            var claims = new[]
            {
                new Claim(ClaimTypes.Name, credentials.Username),
                new Claim(ClaimTypes.Role, "Admin")
            };

            // 获取JWT密钥
            var secretKey = _configuration["Jwt:SecretKey"];
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));

            // 创建JWT令牌
            var token = new JwtSecurityToken(
                issuer: null,
                audience: null,
                claims: claims,
                expires: DateTime.UtcNow.AddHours(1), // 设置过期时间为1小时
                signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
            );

            var tokenHandler = new JwtSecurityTokenHandler();
            var jwtToken = tokenHandler.WriteToken(token);

            return Ok(new { Token = jwtToken });
        }

        return Unauthorized();
    }
}

public class UserCredentials
{
    public string Username { get; set; }
    public string Password { get; set; }
}
  • 创建受保护的接口 :创建一个ProtectedController,用于测试 JWT 的身份验证和授权功能。

csharp

复制代码
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[ApiController]
[Authorize] // 标记需要身份验证的控制器
public class ProtectedController : ControllerBase
{
    [HttpGet]
    public IActionResult GetProtectedData()
    {
        return Ok("This is protected data. Only authenticated users can access this.");
    }
}
  • Vue3 前端
    • 创建项目 :使用vue create vue3-jwt-auth命令创建一个新的 Vue3 项目。
    • 安装依赖 :安装axiosvue-router包,用于发送 HTTP 请求和路由管理。
    • 配置登录逻辑 :在src/views/Login.vue文件中,实现用户登录的界面和逻辑。

html

复制代码
<template>
  <div>
    <h2>Login</h2>
    <form @submit.prevent="login">
      <label for="username">Username:</label>
      <input type="text" id="username" v-model="username" required>
      <br>
      <label for="password">Password:</label>
      <input type="password" id="password" v-model="password" required>
      <br>
      <button type="submit">Login</button>
    </form>
  </div>
</template>

<script>
import axios from 'axios';
import { useRouter } from 'vue-router';

export default {
  data() {
    return {
      username: '',
      password: ''
    };
  },
  methods: {
    async login() {
      const url = 'http://localhost:5000/api/Auth/login';
      const data = {
        username: this.username,
        password: this.password
      };
      try {
        const response = await axios.post(url, data);
        // 将JWT存储在本地存储中
        localStorage.setItem('jwt_token', response.data.Token);
        // 导航到受保护的页面
        this.$router.push('/protected');
      } catch (error) {
        console.error('Login failed:', error);
      }
    }
  }
};
</script>
  • 配置路由和受保护页面 :在src/router/index.js文件中,配置路由和受保护页面的访问权限。

javascript

复制代码
import { createRouter, createWebHistory } from 'vue-router';
import Login from '../views/Login.vue';
import Protected from '../views/Protected.vue';

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'login',
      component: Login
    },
    {
      path: '/protected',
      name: 'protected',
      component: Protected,
      meta: {
        requiresAuth: true // 标记需要身份验证的路由
      }
    }
  ]
});

// 导航守卫,用于验证JWT
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !localStorage.getItem('jwt_token')) {
    next('/');
  } else {
    next();
  }
});

export default router;
  • 创建受保护页面 :在src/views/Protected.vue文件中,创建受保护的页面,用于测试 JWT 的身份验证功能。

html

复制代码
<template>
  <div>
    <h2>Protected Page</h2>
    <p>This is a protected page. Only authenticated users can access this.</p>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  mounted() {
    const token = localStorage.getItem('jwt_token');
    if (token) {
      axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
      // 这里可以发送请求获取受保护的数据
      axios.get('http://localhost:5000/api/Protected')
        .then(response => console.log(response.data))
        .catch(error => console.error('Error:', error));
    }
  }
};
</script>

在上述代码案例中,.NET 后端实现了 JWT 的生成和验证功能,包括用户登录接口、身份验证中间件的配置以及受保护资源的接口。Vue3 前端实现了用户登录界面、JWT 的存储和在请求中携带 JWT 的功能,以及通过路由守卫来控制对受保护页面的访问。通过这个案例,可以看到 JWT 在前后端分离的应用中是如何实现身份验证和授权的。

工具网站

jwt.io 是一个与 JSON Web Token(JWT)相关的工具网站 ,网址为JSON Web Tokens - jwt.io 。其主要功能和特点如下:

功能

  • JWT 解码:能够对 JWT 进行解码,清晰展示 JWT 的三个组成部分,即 Header(头部)、Payload(负载)和 Signature(签名)。将 JWT 字符串粘贴到指定区域,网站会自动解析并以结构化形式呈现头部的算法和令牌类型、负载中的用户信息和声明等内容 ,方便开发者查看 JWT 内部信息,排查问题。例如,可直观看到 Payload 中存放的过期时间、用户 ID、角色等信息。

  • JWT 验证:支持验证 JWT 签名的有效性。开发者输入 JWT 以及对应的签名密钥和算法,网站会依据输入信息校验签名是否正确,判断 JWT 在传输过程中是否被篡改 。比如使用 HMAC SHA256 算法签名的 JWT,输入正确密钥后,网站就能验证其真实性。

  • JWT 生成:可辅助生成 JWT。在网站右侧的 "PAYLOAD" 部分,输入要包含在 JWT 中的信息(如用户 ID、角色、过期时间等,需为 Base64 编码的 JSON 格式 );在 "HEADER" 部分,选择签名算法(如 HMAC SHA256 或 RSA );在 "VERIFY SIGNATURE" 部分,输入签名密钥。完成设置后,网站左侧的 "ENCODED" 部分将展示生成的 JWT 及其头部和载荷信息 。

应用场景

  • 开发调试阶段:开发者在开发涉及 JWT 认证和授权的应用程序时,可利用该网站快速验证 JWT 的结构、内容和签名的正确性,提高开发效率,减少调试时间。比如在前后端分离项目中,后端生成 JWT 后,前端可通过此网站验证接收到的 JWT 是否符合预期。

  • 学习研究场景 :对于学习 JWT 相关知识的人员,通过该网站可以更直观地理解 JWT 的组成结构、工作原理和签名验证机制等内容。例如,通过实际操作生成和解析 JWT,能更好地掌握 JWT 在身份验证和授权中的应用方式。

相关推荐
Larcher27 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐39 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
Jackson@ML1 小时前
用Visual Studio Code最新版开发C#应用程序
ide·vscode·c#
小月鸭1 小时前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu2 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花2 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
她说彩礼65万2 小时前
C# 代理模式
开发语言·c#·代理模式