C# ASP.NET Core 5.0 - 为什么在使用 [Authorization] 时甚至不调用该方法
C# ASP.NET Core 5.0 - Why the method is not even called, when [Authorization] is used
我有 JWT 令牌和 API。
在 startup.cs - 我有 jwt 授权的配置:
public void ConfigureServices(IServiceCollection services)
{
SetupJWTServices(services);
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v3", new OpenApiInfo { Title = "MyTitle", Version = "v3" });
c.OperationFilter<AddSwaggerService>();
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Token authorization",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
});
}
);
}
private static void SetupJWTServices(IServiceCollection services)
{
string key = "secret Public key Token";
var issuer = "myIssuer";
byte[] publicKey = Convert.FromBase64String(key);
var ecdsa = ECDsa.Create();
ecdsa.ImportSubjectPublicKeyInfo(source: publicKey, bytesRead: out _);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = false,
ValidateIssuerSigningKey = true,
ValidIssuer = issuer,
ValidAudience = issuer,
IssuerSigningKey = new ECDsaSecurityKey(ecdsa),
ValidAlgorithms = new[]
{
@"ES256"
}
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint("/swagger/v3/swagger.json", "MyAPIService");
});
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
然后我在控制器中得到了方法,我称之为:
[Authorize]
[HttpGet("CreateNewPassword")]
public IActionResult CreateNewPassword(string Password)
{
if (User.Identity.IsAuthenticated)
{
if (User.Identity is ClaimsIdentity identity)
{
_ = identity.Claims;
}
return Json(new { YourNewHashedPassword = Helpers.GetNewHashedText(Password) });
}
else
{
return Json(new { ErrorMessage = "JWT is invalid!" });
}
}
问题是:
如果我将 [Authorize] 放在方法上方 - 调用时甚至不执行该方法(来自 swagger 和来自邮递员的相同行为)并自动为 401 returned
如果我删除 [Authorize] 行为是 - 根据 JWT 令牌是正确的 - 所以如果 JWT 来自 POSTMAN 无效 - 它 returns 401 with ErrorMessage(没问题) - 如果 JWT来自 POSTMAN 的令牌是可以的 - 它 return 是一个新密码(这只是我的测试方法)
但是!当我删除 [Authorize] 并从 swagger 执行调用时 - 总是有消息 401(没有错误消息) - 因为缺少带有 JWT 令牌的 header。
问题是:
我如何使用 [Authorize] - 因此 swagger 和邮递员将正确执行该方法:
当 JWT 正确时 = 它将以常规方式执行
当 JWT 无效时 = 它将 return 401...
好像认证授权中间件的顺序不对。
你先有 UseAuthorization
。
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
试试这个:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
我有 JWT 令牌和 API。
在 startup.cs - 我有 jwt 授权的配置:
public void ConfigureServices(IServiceCollection services)
{
SetupJWTServices(services);
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v3", new OpenApiInfo { Title = "MyTitle", Version = "v3" });
c.OperationFilter<AddSwaggerService>();
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Token authorization",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
});
}
);
}
private static void SetupJWTServices(IServiceCollection services)
{
string key = "secret Public key Token";
var issuer = "myIssuer";
byte[] publicKey = Convert.FromBase64String(key);
var ecdsa = ECDsa.Create();
ecdsa.ImportSubjectPublicKeyInfo(source: publicKey, bytesRead: out _);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = false,
ValidateIssuerSigningKey = true,
ValidIssuer = issuer,
ValidAudience = issuer,
IssuerSigningKey = new ECDsaSecurityKey(ecdsa),
ValidAlgorithms = new[]
{
@"ES256"
}
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint("/swagger/v3/swagger.json", "MyAPIService");
});
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
然后我在控制器中得到了方法,我称之为:
[Authorize]
[HttpGet("CreateNewPassword")]
public IActionResult CreateNewPassword(string Password)
{
if (User.Identity.IsAuthenticated)
{
if (User.Identity is ClaimsIdentity identity)
{
_ = identity.Claims;
}
return Json(new { YourNewHashedPassword = Helpers.GetNewHashedText(Password) });
}
else
{
return Json(new { ErrorMessage = "JWT is invalid!" });
}
}
问题是:
如果我将 [Authorize] 放在方法上方 - 调用时甚至不执行该方法(来自 swagger 和来自邮递员的相同行为)并自动为 401 returned
如果我删除 [Authorize] 行为是 - 根据 JWT 令牌是正确的 - 所以如果 JWT 来自 POSTMAN 无效 - 它 returns 401 with ErrorMessage(没问题) - 如果 JWT来自 POSTMAN 的令牌是可以的 - 它 return 是一个新密码(这只是我的测试方法)
但是!当我删除 [Authorize] 并从 swagger 执行调用时 - 总是有消息 401(没有错误消息) - 因为缺少带有 JWT 令牌的 header。
问题是:
我如何使用 [Authorize] - 因此 swagger 和邮递员将正确执行该方法: 当 JWT 正确时 = 它将以常规方式执行 当 JWT 无效时 = 它将 return 401...
好像认证授权中间件的顺序不对。
你先有 UseAuthorization
。
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
试试这个:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});