JWT身份验证:.NET Core后台与Vue.js前端实现详解

作者:微信公众号:【架构师老卢】
12-2 8:46
1253

概述:JSON Web Token(JWT)是一种用于安全传输信息的标准。主要用于身份验证和信息传递,通过头部、载荷和签名构成。在.NET Core中,可通过Microsoft.AspNetCore.Authentication.JwtBearer实现后台服务,提供生成、刷新和验证Token的接口。前端使用Vue.js结合axios发送请求,通过拦截器实现自动刷新Token,确保安全可靠的身份验证和信息传递。

什么是JWT?

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间传输信息的轻量级、自包含的标准。JWT由三部分组成:头部(Header)、载荷(Payload)、签名(Signature)。它通常被用于身份验证和信息传递。

  • 头部(Header):声明类型和使用的签名算法。

    {
      "alg": "HS256",
      "typ": "JWT"
    }
    
  • 载荷(Payload):包含声明(claims),是关于实体(通常是用户)和其他数据的声明。

    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
    
  • 签名(Signature):使用密钥对头部和载荷进行签名,以确保数据的完整性和来源验证。

JWT 主要用途

JWT主要用于在网络应用中安全地传递声明。常见用途包括身份认证和信息交换。生成的JWT可以被验证,信任,并且不易被篡改。

JWT 的原理

JWT的原理基于对称或非对称加密。生成JWT时,使用密钥对头部和载荷进行签名。验证时,接收到的JWT通过相同的过程重新计算签名,并与接收到的签名进行比较。由于签名使用密钥生成,只有拥有密钥的一方才能生成有效的签名。

JWT 应用场景

  1. 身份认证:用户登录后,服务器生成JWT,并在每个后续请求中携带JWT,以验证用户身份。

  2. 信息传递:JWT可以包含任意信息,用于在不同系统之间安全传递信息,如用户权限、配置信息等。

JWT 有哪几种传输方式

  1. HTTP Header:JWT通常放在HTTP请求的Authorization头部中,使用Bearer方案,例如:Authorization: Bearer your_token_here

  2. URL 参数:可以将JWT作为URL的查询参数传递。

  3. POST 请求体:可以将JWT放在POST请求体中进行传递。

在 .NET Core 中使用 JWT

后台服务实现

  1. 安装 NuGet 包

    dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
    
  2. 配置 JWT 服务

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_secret_key"))
        };
    });
    
  3. 添加授权中间件

    app.UseAuthentication();
    
  4. 生成 Token 接口

    [ApiController]
    [Route("api/auth")]
    public class AuthController : ControllerBase
    {
        private readonly JwtService _jwtService;
    
        public AuthController(JwtService jwtService)
        {
            _jwtService = jwtService;
        }
    
        [HttpPost("login")]
        public IActionResult Login([FromBody] LoginRequest request)
        {
            // 验证用户名和密码,生成 ClaimsIdentity
            ClaimsIdentity identity = ...
    
            // 生成 JWT
            string token = _jwtService.GenerateToken(identity);
    
            return Ok(new { Token = token });
        }
    }
    
  5. 刷新 Token 接口

    [Authorize]
    [HttpPost("refresh")]
    public IActionResult RefreshToken()
    {
        // 从当前用户的 Claims 中获取信息,生成新的 Token
        ClaimsIdentity identity = ...
    
        string newToken = _jwtService.GenerateToken(identity);
    
        return Ok(new { Token = newToken });
    }
    
  6. 验证 Token 接口

    [Authorize]
    [HttpGet("protected")]
    public IActionResult ProtectedResource()
    {
        // 受保护的资源
        return Ok(new { Message = "This is a protected resource." });
    }
    

前端 VUE 实现

  1. 安装 axios

    npm install axios
    
  2. 在 Vue 组件中使用 JWT

    import axios from 'axios';
    
    // 每次请求前检查 Token 是否过期,如果过期则刷新
    axios.interceptors.request.use(async (config) => {
        const token = localStorage.getItem('jwtToken');
        if (token) {
            // 检查 Token 是否过期
            const decodedToken = parseJwt(token);
            const currentTimestamp = Math.floor(Date.now() / 1000);
    
            if (decodedToken.exp < currentTimestamp) {
                // Token 过期,刷新 Token
                await refreshToken();
            }
    
            config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
    });
    
    // 刷新 Token
    async function refreshToken() {
        const token = localStorage.getItem('jwtToken');
        const response = await axios.post('api/auth/refresh', null, { headers: { Authorization: `Bearer ${token}` } });
    
        const newToken = response.data.Token;
        localStorage.setItem('jwtToken', newToken);
    }
    
    // 发送包含 JWT 的请求
    async function sendRequest() {
        try {
            const response = await axios.get('api/auth/protected');
            console.log(response.data);
        } catch (error) {
            console.error('Request failed:', error);
        }
    }
    
    // 解析 JWT
    function parseJwt(token) {
        const base64Url = token.split('.')[1];
        const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
        const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));
    
        return JSON.parse(jsonPayload);
    }
    

以上是一个简单的示例,实际应用中需要考虑更多的安全性和错误处理。确保在生产环境中使用 HTTPS 以保障数据传输的安全性。

阅读排行