WebApi中添加Jwt鉴权

webapi,添加,jwt · 浏览次数 : 201

小编点评

## JWT Token 创造和验证指南 本指南介绍了创建和验证 JWT 凭据的简单方法,适用于前后端分离的项目。 **项目框架:** .NET Core 3.1 项目,依赖 Swashbuckle.AspNetCoreJWT 项目架构 **主要类:** * **JwtHelper:** 帮助类,提供 JWT 生成和验证方法。 **主要方法:** * **SetJwtEncode:** 将用户数据编码为 JWT 字符串。 * **GetJwtDecode:** 从 JWT 字符串中解码用户数据。 **过滤器:** * **AuthorizeFilter:** 对请求进行授权检查,并验证是否拥有访问特定接口的权限。 **测试:** * **JwtHelper.GetJwtDecode:** 从 JWT 凭据中解码用户数据。 * **JwtHelper.SetJwtEncode:** 将用户数据编码为 JWT 凭据。 **代码示例:** **JwtHelper.cs** ```csharp public static class JwtHelper { private static readonly Logger _logger = new Logger(); private static string secret = ConfigHelper.GetSectionValue("TokenSecret"); public static string SetJwtEncode(Dictionary payload) { try { // ... return token; } catch (System.Exception ex) { _logger.Error(ex.Message); return null; } } public static LoginUserInfo GetJwtDecode(string token) { try { // ... return userInfo; } catch (System.Exception ex) { _logger.Error(ex.Message); return null; } } } ``` **AuthorizeFilter.cs** ```csharp public class AuthorizeFilter : Attribute, IActionFilter { public void OnActionExecuted(ActionExecutedContext context) { } public void OnActionExecuting(ActionExecutingContext context) { var controller = context.RouteData.Values[\"controller\"].ToString(); var action = context.RouteData.Values[\"action\"].ToString(); if (controller == "User" || controller == "Jwt") { // 登录接口不验证 return new JsonResult(new OperationResult(OperationResultType.Error, "此接口必须携带token访问!请登录携带Token访问")); } else { // 验证token var authHeader = context.HttpContext.Request.Headers["Authorization"]; if (string.IsNullOrWhiteSpace(authHeader)) { return new JsonResult(new OperationResult(OperationResultType.Error, "token验证失败:您没有权限调用此接口,请登录重新获取Token")); } else { var token = authHeader.Substring(7).Replace("Bearer ", ""); var userInfo = JwtHelper.GetJwtDecode(token); if (userInfo != null) { return new JsonResult(new OperationResult(OperationResultType.Error, "Token验证失败")); } // 验证token有效期 return new JsonResult(new OperationResult(OperationResultType.Success, "token验证成功")); } } } } ``` **测试:** ```csharp // 测试JwtHelper.GetJwtDecode var token = "YOUR_JWT_TOKEN"; var userInfo = JwtHelper.GetJwtDecode(token); Console.WriteLine(userInfo.username); Console.WriteLine(userInfo.pwd); // 测试JwtHelper.SetJwtEncode var payload = new Dictionary(); payload["username"] = "your_username"; payload["pwd"] = "your_password"; var encodedToken = JwtHelper.SetJwtEncode(payload); Console.WriteLine(encodedToken); ``` **运行并查看结果:** 运行代码并访问一个需要授权的接口,例如 `/api/user`。 如果登录成功,将看到以下消息: ``` your_username your_password ``` 如果登录失败,将看到以下消息: ``` token验证失败:您没有权限调用此接口,请登录重新获取Token ```

正文

前言

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息。一个 JWT 实际上就是一个字符串,它由三部分组成,头部、载荷与签名。前两部分需要经过 Base64 编码,后一部分通过前两部分 Base64 编码后再加密而成。针对前后端分离的项目,大多是通过 token 进行身份认证来进行交互,今天将介绍一种简单的创建 和验证token 的方式 。

image

项目介绍

项目框架:.NET Core 3.1

项目依赖:

  • Swashbuckle.AspNetCore

  • JWT

项目架构:

image

项目核心代码

JWT帮助类

  /// <summary>
    /// JWT获取和验证帮助类
    /// </summary>
    public class JwtHelper
    {
        /// <summary>
        /// 日志
        /// </summary>
       private static Logger  _logger = new Logger();

        /// <summary>
        /// 私钥appsettings.json中配置
        /// </summary>
        private static string secret =  ConfigHelper.GetSectionValue("TokenSecret");

        /// <summary>
        /// 生成JwtToken
        /// </summary>
        /// <param name="payload">不敏感的用户数据</param>
        /// <returns></returns>
        public static string SetJwtEncode(Dictionary<string, object> payload)
        {
            try
            {
                IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
                IJsonSerializer serializer = new JsonNetSerializer();
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

                var token = encoder.Encode(payload, secret);
                return token;
            }
            catch (System.Exception ex)
            {
                _logger.Error(ex.Message);
                return null;
            }

        }

        /// <summary>
        /// 根据jwtToken获取实体
        /// </summary>
        /// <param name="token">jwtToken</param>
        /// <returns></returns>
        public static LoginUserInfo GetJwtDecode(string token)
        {
            try
            {
                IJsonSerializer serializer = new JsonNetSerializer();
                IDateTimeProvider provider = new UtcDateTimeProvider();
                IJwtValidator validator = new JwtValidator(serializer, provider);
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtDecoder decoder = new JwtDecoder(serializer, urlEncoder);
                //IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);
                var userInfo = decoder.DecodeToObject<LoginUserInfo>(token, secret, verify: true);//token为之前生成的字符串
                return userInfo;
            }
            catch (System.Exception ex)
            {
                _logger.Error(ex.Message);
                return null;
            }

        }

    }

过滤器Filter

 /// <summary>
    /// 授权认证
    /// </summary>
    public class AuthorizeFilter : Attribute, IActionFilter
    {

        public void OnActionExecuted(ActionExecutedContext context)
        {

        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            var controller = context.RouteData.Values["controller"].ToString();
            //var action = context.RouteData.Values["action"].ToString();
            if (controller == "User" || controller == "Jwt")
            {
                //登录接口不验证
            }
            else
            {
                var authHeader = context.HttpContext.Request.Headers["Authorization"];
                if (string.IsNullOrWhiteSpace(authHeader))
                {
                    //此接口必须携带token访问!
                    context.Result = new JsonResult(new OperationResult(OperationResultType.Error, "此接口必须携带token访问,请登录携带Token访问"));
                }
                else //字段值不为空
                {
                    authHeader = authHeader.ToString().Replace("Bearer", "").Trim();//去掉Bearer字串
                    if (authHeader == "")
                    {
                        context.Result = new JsonResult(new OperationResult(OperationResultType.Error, "token验证失败:您没有权限调用此接口,请登录重新获取Token"));
                    }
                    else
                    {
                        LoginUserInfo LoginInfo = JwtHelper.GetJwtDecode(authHeader);
                        if (LoginInfo != null)
                        {
                            context.Result = new JsonResult(new OperationResult(OperationResultType.Error, "Token验证失败"));
                        }
                        string UserName = LoginInfo.username;
                        string PassWord = LoginInfo.pwd;
                        string ExpireTimeStamp = LoginInfo.exp;
                        //var cacheToken = Cache.Get(UserName);
                        if (isTokenExpire(ExpireTimeStamp)) //这里应该验证有效期
                        {
                            context.Result = new JsonResult(new OperationResult(OperationResultType.Error, "token验证失败:您没有权限调用此接口,请登录重新获取Token"));
                        }
                    }

                }
            }
        }

        /// <summary>
        /// 时间戳字符串
        /// </summary>
        /// <param name="timestampstr"></param>
        /// <returns></returns>
        private bool isTokenExpire(string timestampstr)
        {
            try
            {
                double timestamp = double.Parse(timestampstr);
                System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));//当地时区
                var expireTime = startTime.AddSeconds(timestamp);
                if (expireTime > DateTime.Now)
                {
                    return false;//未过期
                }
                else
                {
                    return true;//已过期
                }
            }
            catch (Exception ex)
            {
                return true;
            }
        }

    }

测试验证

Swagger页面

image

登录获取Token

image

未携带token访问接口

image

源码获取

关注公众号,后台回复关键字:JwtApiDemo

与WebApi中添加Jwt鉴权相似的内容:

WebApi中添加Jwt鉴权

前言 JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息。一个 JWT 实际上就是一个字符串,它由三部分组成,头部、载荷与签名。前两部分需要经过 Base64 编码,后一部分通过前两部分 Base64 编码后再加密而成。针对

基于webapi的websocket聊天室(番外一)

上一篇我已经实现了聊天室,并且在协议中实现了4种类型的消息传输。其实还可以添加video,audio,live等等类型。 不过假如把目前的协议看作RCP1.0版的话,这个版本就只支持有限的4种消息。精力有限啊。也许RCP2.0就可以把video,audio类型加进去? 这不是这篇番外考虑的。而是我在

Clear Code for Minimal API

我在写MinimalAPI的时候,发现不能最清晰的看到每个API,原因就是:WebAPI中不断增长逻辑处理过程 于是我在想如何简化API至一行,在一点一点想办法中,发现了简化DotNET Minimal API的方式。特此记录下来这个思路给需要帮助的人。我的灵感来源于 C# 11 功能 - 接口中的

造轮子之asp.net core identity

在前面我们完成了应用最基础的功能支持以及数据库配置,接下来就是我们的用户角色登录等功能了,在asp.net core中原生Identity可以让我们快速完成这个功能的开发,在.NET8中,asp.net core identity支持了WebApi的注册登录。这让我们在WebApi中可以更爽快的使用

.Net8 AddKeyedScoped键值key注册服务异常

异常描述:This service descriptor is keyed. Your service provider may not support keyed services. 场景:.Net8 WebAPI应用程序中使用AutoFac替代了默认的DI容器 当使用键值注册服务后: build

基于 ActionFilters 的限流库DotNetRateLimiter使用

前言 在构建API项目时,有时出于安全考虑,防止访问用户恶意攻击,希望限制此用户ip地址的请求次数,减轻拒绝服务攻击可能性,也称作限流。接下来,我们就来学习开源库DotNetRateLimiter 如何轻松实现限流。 项目使用配置 安装Nuget包 在新建立的WebAPI项目中,通过Nuget包管理

如何在 Net6.0 中对 WebAPI 进行 JWT 认证和授权

一、简介 我们做微服务开发,或者说做分布式开发,有一项技术我们是避不开的,那就是WebAPI,在 Net6.0中,有两类 WebAPI,一类是极简 WebAPI,它砍掉了很多冗余的东西,更纯粹的是做 API的,也更适合做微服务的开发。另外一类就是我们通常使用的正常 API,这个没得说,也是我们使用最

前端项目通过‘URL 重写’部署在 IIS 中,访问 WebAPI 接口

本文将简单介绍前端项目在 IIS 中部署,以及‘URL重写’功能模块的安装、配置,最后是日常遇到的问题解决方案。

C#中关于 object,dynamic 一点使用心得

首先说一下使用场景 WebAPI接口入参使用 object和 dynamic 后续解析和处理 1.object和dynamic 区别 在.NET中,object和dynamic也有一些区别: object:object是.NET中的顶级类,所有类都是object的子类。在C#中,您可以使用objec

OData WebAPI实践-OData与EDM

本文属于 OData 系列 引言 在 OData 中,EDM(Entity Data Model) 代表“实体数据模型”,它是一种用于表示 Web API 中的结构化数据的格式。EDM 定义了可以由 OData 服务公开的数据类型、实体和关系。 EDM 也提供了一些规则来描述数据模型中的实体之间的关