netCore自定义中间件限制用户同时登录

.netcore中间件的定义很奇怪,不需要继承什么,只需要有一个关键的方法就行。InvokeAsync方法内有一个参数HttpContext 当前请求上下文。再一个就是要有一个RequestDelegate。

直接上代码

 private readonly ICache _cache;
        private readonly RequestDelegate _next;
        public LoginOneMiddleware(RequestDelegate next, IServiceProvider service)
        {
            _next = next;
            _cache = service.GetRequiredService<ICache>();
        }
        public Task InvokeAsync(HttpContext httpContext)
        {
            var user = httpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.UserData);
            var requestUrl = httpContext.Request.Path.Value;
             //这里如果请求的是登录的接口,不做判断
            if(user != null && !requestUrl.Contains("/login")) {
                var token = httpContext.Request.Headers[token"].ToString();            
                var username = user.Value;
                if(_cache.ContainsKey(username)) {
                    var cachToken = _cache.Get<string>(username);
                    if(token != cachToken) {
                        httpContext.Response.Clear();
                        httpContext.Response.ContentType = "application/json;charset=utf-8";
                        var responseStr = "登录已过期";
                        // httpContext.Response.StatusCode = 401;
                        httpContext.Response.WriteAsync(responseStr);
                        return Task.CompletedTask;
                    }
                }
                else {
                    _cache.Add(username, token, 60 * 60 * 24);
                }
            }

            return _next(httpContext);
        }

    说下简单思路,登录的时候把生成的token放到redis里面,把用户名当作key,值就是token。如果key存在就更新,用新的token替换掉。然后中间件这里先获取到当前请求的token和用户名,根据用户名找到redis里面用户名这个key对应的值,和当前的token对比,如果不一致就说明是被覆盖了,这时候返回401,让用户重新登录。

添加好中间件之后,用扩展方法添加中间件

public static IApplicationBuilder UseLogin(this IApplicationBuilder app)
{
   return app.UseMiddleware<LoginOneMiddleware>();
}

然后再startup里面添加中间件即可

app.UseLogin();

posted @ 2022-01-05 18:04  不是玩的  阅读(434)  评论(0编辑  收藏  举报