.Net Core下简单的JWT黑名单中间件

12 篇文章 2 订阅
本文介绍了如何通过JWT(JSON Web Token)的黑名单来阻止特定Token的登录。选择IDistributedCache作为分布式缓存存储JWT黑名单,当用户发起退出登录请求时,将Token写入黑名单。代码示例展示了在ASP.NET Core中如何实现这一机制,确保Token在过期后自动释放,同时检查请求是否包含标记以决定是否将Token加入黑名单。
摘要由CSDN通过智能技术生成

自从JWT认证方式在互联网上蔓延后,Session认证方式就被挤掉了一大半的生存空间,这里我们不讲JWT与Session两种方式的优缺点,我们只讲如何通过JWT的黑名单来阻止某些Token的登录。

设置黑名单,也就是说要将Token写入某个存储介质,然后考虑数据并不需要一直存在,其在有效期之后应自动释放,那这种情况下存储介质首选肯定是缓存,鉴于目前流行容器化技术,微服务概念又漫天飞的情况,缓存还得考虑支持分布式,那妥妥的必选方案就是IDistributedCache,这样究竟是单体应用MemoryCache,还是分布式Redis,亦或是其它方式都可以任君选择。

选好了存储介质,那就要确定程序通过什么标志来判断确定当前是要将Token写入黑名单,一般来说Authorization是写在HttpHeader里,那我们也可以考虑在HttpHeader里增加一个Key来标志当前请求是要注册黑名单,这里我们选用Loginout,毕竟一般来说也就是退出登录时,才需要设置黑名单。

下面开始来具体的代码,这里是按照微软定义的Restful规范通过StatusCode来返回执行结果

    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Caching.Distributed;
    public class JWTBlacklistMiddleware
    {
        private const string AuthenticationHeader = "Authorization";
        private const string AuthenticationScheme = "Bearer";
        private const string LoginoutHeader = "Loginout";//退出登录的Header
        private const int CacheExpiration = 36000;//缓存过期时间 秒,不解析jwt数据,直接将缓存时间设置为Token的最大有效时间,以空间换性能

        private readonly RequestDelegate _next;
        private readonly IDistributedCache _cache;

        public JWTBlacklistMiddleware(RequestDelegate next, IDistributedCache cache)
        {
            this._next = next;
            this._cache = cache;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var auth = context.Request.Headers[AuthenticationHeader].FirstOrDefault();
            if (!string.IsNullOrWhiteSpace(auth) && auth.StartsWith(AuthenticationScheme))
            {
                var token = auth.Substring(AuthenticationScheme.Length).Trim();
                var tokenMd5 = MD5Helper.HashOf(token);//通过摘要方式降低存储空间,如果担心碰撞问题导致不应该过期的Token也过期了,可以将整个Token作为Key的一部分,Redis的Key支持512M
                var cacheKey = $"TokenBLK:{tokenMd5}";
                if (context.Request.Headers[LoginoutHeader].FirstOrDefault() != null)//只要带了LoginoutHeader并且value不为null,就认为是要记录黑名单
                {
                    //将Token的摘要写入黑名单
                    await this._cache.SetStringAsync(cacheKey, "1", new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(CacheExpiration)
                    });
                    context.Response.StatusCode = 200;
                    return;
                }
                else if ((await this._cache.GetStringAsync(cacheKey)) != null)
                {//如果是黑名单,直接返回401
                    context.Response.StatusCode = 401;
                    return;
                }
            }
            await this._next(context);
        }
    }

上面代码中的MD5Helper具体源码可见此处
使用时也只需要在StartupUseMiddleware,然后需注意下Use的位置,一般来说应该在UseStaticFiles之后,在UseAuthentication之前

        public void Configure(IApplicationBuilder app, IHostEnvironment env)
        {
            app.UseMiddleware<JWTBlacklistMiddleware>();
        }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值