如何根据URL ASP.NET核心中的用户名手动验证JWT



我正在尝试为API使用MVC和JWT的ASP.NET身份框架。要求是访问用户名/设备的API在URL中,例如API/V1/用户名/帐户。JWT是问题的用户或设备中都有用户名。我可以在startup.cs文件中进行吗?直到最近,下面的代码正常工作正常,它通过允许ASP.NET身份使用JWT受保护的API来开始做奇怪的事情。我想检查URL API/V1/用户名中的用户名是否匹配令牌一个。键是我的代码。感谢您的见解。

 public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
             Configuration = builder.Build();
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel
            .Warning()
            .WriteTo.RollingFile("Logs/GateKeeperLog-{Date}.txt")
            .CreateLogger();
    }
    public static IConfigurationRoot Configuration { get; set; }
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton(Configuration);
        services.AddDbContext<GkEnterpriseContext>(options =>
        options.UseSqlServer(Configuration["Database:Connection"]));
        services.AddTransient<IUnitOfWork, UnitOfWork>();
        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<GkEnterpriseContext>()
            .AddDefaultTokenProviders();
        services.AddMvc()
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.Formatting = Formatting.Indented;
            }).AddJsonOptions(options =>
            {
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            });
        services.AddTransient<IEmailSender, AuthMessageSender>();
        services.AddTransient<ISmsSender, AuthMessageSender>();
    }
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddSerilog();
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
         app.UseWhen(context => context.Request.Path.Value.Contains("/api")
        , builder =>
        {
            builder.UseJwtBearerAuthentication(new JwtBearerOptions
            {
                AutomaticAuthenticate = true,
                AutomaticChallenge = true,
                TokenValidationParameters = new TokenValidationParameters
                {
                    ValidIssuer = Configuration["Tokens:Issuer"],
                    ValidAudience = Configuration["Tokens:Audidence"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes
                        (JwtTokenIssuer.PrivateKey)),
                    ValidateLifetime = true,
                    NameClaimType = JwtRegisteredClaimNames.FamilyName
                }
            });
            app.UseWhen(context => context.Request.Path.Value.StartsWith("/api/v2/computers/")
                , builder1 =>
                    builder1.MapWhen((ctx) =>
                    {
                        var deviceName = ctx.User.Claims.SingleOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.Name)?.Value ?? "";
                        var testPath = new Microsoft.AspNetCore.Http.PathString($"/api/v2/computers/{deviceName}");
                        var pathMatch = ctx.Request.Path.StartsWithSegments(testPath);
                        return String.IsNullOrWhiteSpace(deviceName) || !pathMatch;
                    }, cfg =>
                    {
                        cfg.Run((req) =>
                        {
                            req.Response.StatusCode = 403;
                            return req.Response.WriteAsync("Sorry , you cant access this resource...");
                        });
                    }));

        });

        app.UseIdentity();
        app.UseStatusCodePagesWithReExecute("/StatusCodes/{0}");
        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
            routes.MapRoute(
                name: "defaultApi",
                template: "api/v2/{controller}/{id?}");
        });


    }
}

//jwt issung代码块,现在正在按预期发出令牌,只有验证才是问题。

 var claims = new[]
            {
                new Claim(JwtRegisteredClaimNames.Sub,computer),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.FamilyName,"GkDevice")
            };
            var key = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(PrivateKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                issuer: Startup.Configuration["Tokens:Issuer"],
                audience: Startup.Configuration["Tokens:Audidence"],
                claims: claims,
                notBefore: DateTime.Now,
                expires: DateTime.Now.AddYears(10),
                signingCredentials: creds
            );
            var data = new Token
            {
                Message = "New Token was issued",
                Jwt = new JwtSecurityTokenHandler().WriteToken(token),
                Iat = GkHelpers.ConvertTimeToEpoch(token.ValidFrom) ,
                Exp = GkHelpers.ConvertTimeToEpoch(token.ValidTo)
            };
            return data;

类似的东西可能会帮助您 -

app.UseWhen(context => context.Request.Path.Value.StartsWith("/api"), builder =>
{
    ...jwt code...
    builder.MapWhen((ctx) =>
    {
        var userName = ctx.User.Claims.SingleOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.Name)?.Value ?? "";
        var testPath = new Microsoft.AspNetCore.Http.PathString($"/api/v2/computers/{userName}/");
        var pathMatch = ctx.Request.Path.StartsWithSegments(testPath);
        return String.IsNullOrWhiteSpace(userName) || !pathMatch;
    }, cfg =>
    {
        cfg.Run((req) =>
        {
            req.Response.StatusCode = 403;
            return req.Response.WriteAsync("");
        });
    });
});

当"名称"声明中的用户名(配置如何在此处获取用户名)中的用户名与给定的路径不匹配时,内部MapWhen将触发。然后,它将立即执行以下请求管道,该管道将返回带有空响应主体的403代码。

我不确定,如果您可以在同一请求管道中处理与身份相关的项目,实际上您添加身份。当用途之外,您可能必须提取代码时提取该地图。

相关内容

  • 没有找到相关文章

最新更新