Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# JWT身份验证,忽略Authorize属性中定义的角色_C#_Asp.net Core_Jwt_Authorization_Asp.net Identity - Fatal编程技术网

C# JWT身份验证,忽略Authorize属性中定义的角色

C# JWT身份验证,忽略Authorize属性中定义的角色,c#,asp.net-core,jwt,authorization,asp.net-identity,C#,Asp.net Core,Jwt,Authorization,Asp.net Identity,在尝试使用JWT作为默认身份验证方案来实现基于角色的身份验证时,我遇到了一种情况,即忽略了Authorize属性中定义的角色,允许任何请求(带有有效令牌)通过,即使不在这些角色中,(有趣的是,在相同的Authorize属性中定义了自定义需求的其他策略工作正常) 阅读时他提到 这里有一个很好的发现:ASP.NET Core中的JWT中间件知道如何解释JWT负载中的“角色”声明,并将适当的声明添加到声明实体。这使得对角色使用[Authorize]属性非常容易 以及: 这是一个非常有趣的地方,当你考虑

在尝试使用JWT作为默认身份验证方案来实现基于角色的身份验证时,我遇到了一种情况,即忽略了
Authorize
属性中定义的角色,允许任何请求(带有有效令牌)通过,即使不在这些角色中,(有趣的是,在相同的
Authorize
属性中定义了自定义需求的其他策略工作正常)

阅读时他提到

这里有一个很好的发现:ASP.NET Core中的JWT中间件知道如何解释JWT负载中的“角色”声明,并将适当的声明添加到
声明实体
。这使得对角色使用
[Authorize]
属性非常容易

以及:

<>这是一个非常有趣的地方,当你考虑把角色传递给<代码> [授权] < /> >实际上会查看是否有一个具有你所授权的角色的值的类型声明。这意味着我可以简单地添加<代码> [授权(角色=“admin”)]。到任何API方法,这将确保只有有效负载包含声明“roles”(包含角色数组中的Admin值)的JWT才会被授权使用该API方法

这仍然成立吗?(这篇文章已经有好几年了)
我做错什么了吗

启动(配置服务)

public void配置服务(IServiceCollection服务)
{
字符串defaultConnection=Configuration.GetConnectionString(“默认”);
services.AddDbContext(options=>options.UseSqlServer(defaultConnection.UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll));
服务.额外性()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
services.AddAuthorization(o=>o.AddPolicy(Policy.IsInTenant,x=>x.AddRequirements(new-isintenanterrequirement()));
services.AddAuthentication(x=>
{
x、 DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme;
x、 DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x=>
{
x、 SaveToken=true;
x、 TokenValidationParameters=新的TokenValidationParameters
{
IssuerSigningKey=新对称性安全密钥(密钥),
validateisuer=true,
ValidateAudience=true,
ValidAudience=“某个主机…”,
ValidIssuer=“somehost…”,
};
});
}
启动(配置)

public void配置(IApplicationBuilder应用程序,IWebHostEnvironment)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(x=>x.MapController());
}
控制器:

[ApiController]

[Authorize(Roles=“some_random_string_which_not_registered_anywhere”)]/以下是关于如何使用JWT基于角色的身份验证的完整工作演示:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidIssuer = Configuration["Jwt:JwtIssuer"],
                ValidAudience = Configuration["Jwt:JwtIssuer"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:JwtKey"])),
                ValidateIssuer = true, 
                ValidateAudience = true,
                ValidateIssuerSigningKey = true,
            };
        });       
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseHttpsRedirection();
    app.UseRouting();

    app.UseAuthentication(); 
        
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapControllers();
    });
}
在appSettings.json中存储
发行人
受众
签名密钥

"jwt": {
    "JwtKey": "YourJwtKey",
    "JwtIssuer": "YourJwtIssuer"
}
生成令牌:

[Route("api/[Controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    private IConfiguration _config;
    public ValuesController(IConfiguration config)
    {
        _config = config;
    }
    [Route("GenerateToken")]
    public async Task<IActionResult> GenerateToken()
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Role, "Admin")
        };
        var token = new JwtSecurityToken(_config["Jwt:JwtIssuer"],
                                         _config["Jwt:JwtIssuer"],
                                         claims: claims,
                                         expires: DateTime.Now.AddDays(5),
                                         signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:JwtKey"])),
                                             SecurityAlgorithms.HmacSha256));
        var data = new JwtSecurityTokenHandler().WriteToken(token);
        return Ok(new { data });                   
    }
}
[路由(“api/[控制器]”)]
[ApiController]
公共类值控制器:控制器库
{
私有IConfiguration\u config;
公共价值控制器(IConfiguration配置)
{
_config=config;
}
[路线(“GenerateToken”)]
公共异步任务GenerateToken()
{
var索赔=新列表
{
新索赔(ClaimTypes.Role,“Admin”)
};
var-token=新的JwtSecurityToken(_-config[“Jwt:JwtIssuer”],
_配置[“Jwt:JwtIssuer”],
索赔:索赔,
过期日期:DateTime.Now.AddDays(5),
signingCredentials:new signingCredentials(新的SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config[“Jwt:JwtKey”])),
SecurityAlgorithms.HmacSha256);
var data=new JwtSecurityTokenHandler().WriteToken(令牌);
返回Ok(新的{data});
}
}
试验方法:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [Authorize(Roles = "admin")]
    [HttpGet]
    public async Task<IActionResult> Get()
    {

        return Ok();
    }
    [Authorize(Roles = "Admin")]
    [HttpGet("GetAdmin")]
    public async Task<IActionResult> GetAdmin()
    {

        return Ok();
    }
}
[ApiController]
[路线(“[控制器]”)]
公共类WeatherForecastController:ControllerBase
{
[授权(Roles=“admin”)]
[HttpGet]
公共异步任务Get()
{
返回Ok();
}
[授权(Roles=“Admin”)]
[HttpGet(“GetAdmin”)]
公共异步任务GetAdmin()
{
返回Ok();
}
}
结果:

参考:


以下是关于如何使用JWT基于角色的身份验证的完整演示:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidIssuer = Configuration["Jwt:JwtIssuer"],
                ValidAudience = Configuration["Jwt:JwtIssuer"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:JwtKey"])),
                ValidateIssuer = true, 
                ValidateAudience = true,
                ValidateIssuerSigningKey = true,
            };
        });       
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseHttpsRedirection();
    app.UseRouting();

    app.UseAuthentication(); 
        
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapControllers();
    });
}
在appSettings.json中存储
发行人
受众
签名密钥

"jwt": {
    "JwtKey": "YourJwtKey",
    "JwtIssuer": "YourJwtIssuer"
}
生成令牌:

[Route("api/[Controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    private IConfiguration _config;
    public ValuesController(IConfiguration config)
    {
        _config = config;
    }
    [Route("GenerateToken")]
    public async Task<IActionResult> GenerateToken()
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Role, "Admin")
        };
        var token = new JwtSecurityToken(_config["Jwt:JwtIssuer"],
                                         _config["Jwt:JwtIssuer"],
                                         claims: claims,
                                         expires: DateTime.Now.AddDays(5),
                                         signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:JwtKey"])),
                                             SecurityAlgorithms.HmacSha256));
        var data = new JwtSecurityTokenHandler().WriteToken(token);
        return Ok(new { data });                   
    }
}
[路由(“api/[控制器]”)]
[ApiController]
公共类值控制器:控制器库
{
私有IConfiguration\u config;
公共价值控制器(IConfiguration配置)
{
_config=config;
}
[路线(“GenerateToken”)]
公共异步任务GenerateToken()
{
var索赔=新列表
{
新索赔(ClaimTypes.Role,“Admin”)
};
var-token=新的JwtSecurityToken(_-config[“Jwt:JwtIssuer”],
_配置[“Jwt:JwtIssuer”],
索赔:索赔,
过期日期:DateTime.Now.AddDays(5),
signingCredentials:new signingCredentials(新的SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config[“Jwt:JwtKey”])),
SecurityAlgorithms.HmacSha256);
var data=new JwtSecurityTokenHandler().WriteToken(令牌);
返回Ok(新的{data});
}
}
试验方法:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [Authorize(Roles = "admin")]
    [HttpGet]
    public async Task<IActionResult> Get()
    {

        return Ok();
    }
    [Authorize(Roles = "Admin")]
    [HttpGet("GetAdmin")]
    public async Task<IActionResult> GetAdmin()
    {

        return Ok();
    }
}
[ApiController]
[路线(“[控制器]”)]
公共W类
public class IsInTenantRequirement : IAuthorizationRequirement { }

public class IsInTenantAuthorizationHandler : AuthorizationHandler<IsInTenantRequirement>
{
    private readonly RouteData _routeData;

    public IsInTenantAuthorizationHandler(IHttpContextAccessor httpContextAccessor)
    {
        _routeData = httpContextAccessor.HttpContext.GetRouteData();
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsInTenantRequirement requirement)
    {
        var tenantIdFromRequest = _routeData.Values["tenantId"]?.ToString();
        var tenantId = context.User.FindFirstValue(AppClaim.TenantId);

        if (tenantIdFromRequest == tenantId)
        {
            context.Succeed(requirement);
        }
        context.Succeed(requirement);


        return Task.CompletedTask;
    }
}