繁体   English   中英

ASP.NET core 3 使用 jwt 自定义身份验证

[英]ASP.NET core 3 Customized authentication with jwt

我在我的项目中使用 jwt 令牌。 当客户端登录时,他将收到一个带有他的设备 ID(在移动设备中)的令牌 - 在请求正文中发送到服务器 - 作为有效负载......

我想要做的事情是当客户端在正文中发送他的设备 ID(作为我项目中的约定)以及标头请求中的令牌时的进一步请求,我想检查设备 ID 和令牌的有效负载是否相等。

我在这样的服务中做到了这一点:

public class AuthenticationService
{
    public bool IsAuthenticated(HttpRequest req, string deviceId)
    {


        var token = req.Headers["authorization"];
        var handler = new JwtSecurityTokenHandler();

        JwtSecurityToken tokenS;  

        foreach (var stringValue in token)
        {
            var ss = stringValue.Replace("Bearer ", "");
            if (handler.CanReadToken(ss))
            {
                tokenS = handler.ReadToken(ss) as JwtSecurityToken;
                return tokenS.Claims.Any(c => c.Value == deviceId);

            }
        }

        return false;
    }
}

我应该将它注入到我想要授权用户的每个控制器中......

if (_authenticationService.IsAuthenticated(Request, deviceId))
        {
            _logger.LogInformation("authorized!");
        }
        else
        {
            _logger.LogCritical("unauthorized");
        }

我想知道是否有更清洁的方法来做到这一点? 当我配置身份验证时,在 Startup 类中要做的事情:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(
                        Configuration.GetSection("AppSettings:Token").Value)),
                    ValidateIssuer = false,
                    ValidateAudience = false,

                };
            });

AddJwtBearer扩展会将令牌中的声明映射到用户的 cliams ,您可以通过(如果 cliam 类型为deviceId )获取设备 ID:

var deviceID= context.HttpContext.User.Claims.Where(x => x.Type == "deviceId").FirstOrDefault().Value;

然后,您可以使用 Filter 或 Middleware 读取请求正文并将 reuqest body 中的设备 ID 与 User's claim 中的设备 ID 进行比较。 例如,如果使用过滤器:

public class CustomActionFilter : ActionFilterAttribute
{
    public override async void OnActionExecuting(ActionExecutingContext context)
    {

        if (context.HttpContext.User.Identity.IsAuthenticated) { 

        //read request body 
        var bodyStr = "";
        var req = context.HttpContext.Request;
        req.EnableBuffering();
        req.Body.Position = 0;
        using (var stream = new StreamReader(req.Body))
        {
            bodyStr = await stream.ReadToEndAsync();
        }

        // here you get device ID from bodyStr ,for example : deviceIDFromReq

        var deviceID= context.HttpContext.User.Claims.Where(x => x.Type == "deviceId").FirstOrDefault().Value;

        // then compare 

        if (deviceIDFromReq.Equals(deviceID))
        {
            context.Result = new BadRequestObjectResult(new
            {
                status = "error",
                description = "deviceID not matched"
            });
        }
        }
        base.OnActionExecuting(context);
    }
}

注册为全局过滤器:

services.AddControllers(config =>
{
    config.Filters.Add<CustomActionFilter>();

});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM