JSON Web Token(JWT)是一种用于在网络应用间安全地传递信息的紧凑、自包含的方式。以下是关于 JWT 认证服务器更详细的介绍,包括其意义、作用、工作原理、组成部分、时效性相关内容、搭建条件以及代码案例。
JWT 的意义与作用
- 意义:在分布式系统和前后端分离的架构中,JWT 提供了一种安全、便捷的身份验证和授权机制,使得不同的服务和应用之间能够可靠地识别用户身份和权限信息,同时保证信息的安全性和完整性。
- 作用
- 身份验证:用户登录后,服务器生成 JWT 并返回给客户端。客户端在后续请求中携带 JWT,服务器通过验证 JWT 来确定用户的身份,判断用户是否有权访问受保护的资源。
- 授权:JWT 中可以包含用户的角色、权限等信息,服务器根据这些信息来授权用户对不同资源的访问权限,实现细粒度的访问控制。
- 信息传递:可以在 JWT 中携带一些用户相关的信息,如用户名、用户 ID 等,这些信息可以在不同的服务之间传递,避免了多次查询数据库来获取用户信息,提高了系统的性能和效率。
JWT 的工作原理
- 用户登录:用户在客户端输入用户名和密码等登录信息,发送登录请求到服务器。
- 服务器验证:服务器接收到登录请求后,对用户提交的信息进行验证。如果验证通过,服务器根据用户信息生成 JWT。
- 生成 JWT:JWT 由三部分组成,分别是 Header(头部)、Payload(负载)和 Signature(签名)。服务器将用户的相关信息(如用户 ID、角色、权限等)放入 Payload 中,并使用密钥对 Header 和 Payload 进行签名,生成 Signature。然后将这三部分用点号(.)连接起来,形成一个完整的 JWT 字符串。
- 返回 JWT:服务器将生成的 JWT 作为响应返回给客户端。
- 客户端存储和使用 :客户端收到 JWT 后,通常会将其存储在本地(如浏览器的 Local Storage 或 Session Storage 中)。在后续的请求中,客户端会在请求头的
Authorization
字段中携带 JWT,将其发送给服务器。 - 服务器验证:服务器接收到带有 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,确保只有经过身份验证和授权的用户才能访问受保护的资源。在.NET 的ASP.NET Core 中,可以使用
JwtBearer
中间件来实现 JWT 的验证和授权功能。
代码案例
下面是一个简单的.NET + Vue3 的 JWT 认证服务器代码案例。
- .NET 后端(ASP.NET Core)
- 创建项目 :使用
dotnet new webapi
命令创建一个新的ASP.NET Core Web API 项目。 - 安装依赖 :安装
Microsoft.AspNetCore.Authentication.JwtBearer
和Microsoft.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 项目。 - 安装依赖 :安装
axios
和vue-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 在身份验证和授权中的应用方式。