基于JWT的授权.NET core 2.0 web api。政策授权无效

时间:2017-11-29 22:14:34

标签: asp.net-core-webapi

我无法通过我的.NET Core 2.0 web api应用程序中的策略([Authorize(Policy = "AdminAccess")])进行授权。 我使用基于JWT的身份验证,它几乎可以工作。是的,差不多。 我有ValuesController有3个方法:

[Route("api/values")]
GetValues()

[Authorize]
[Route("api/secretvalues")]
GetSecretValues()

[Authorize(Policy = "AdminAccess")]
[Route("api/adminsecretvalues")]
GetAdminSecretValues()

我能够从不受保护的方法api /值中获取值。当我试图达到api / secretvalues,受[授权]保护时,我得到了401错误,没问题。然后我可以在我的TokenController中调用api / token,我收到令牌,如果我在下次调用api / secretvalues时使用它一切正常,我可以看到受保护的数据。但第三种方法不起作用。我总是得到未经授权。我在.NET Core 2.0 JWT的mozaic中缺少一些小部分,但我不知道它是什么。

这是我的代码:

Startup.cs

namespace JwtWebApplication
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<TokenAuthenticationSettings>(Configuration.GetSection("TokenAuthentication"));

            string key = Configuration.GetSection("TokenAuthentication:Key").Value;
            var securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key));

            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = securityKey,
                ValidateIssuer = true,
                ValidIssuer = Configuration.GetSection("TokenAuthentication:Issuer").Value,
                ValidateAudience = true,
                ValidAudience = Configuration.GetSection("TokenAuthentication:Audience").Value,
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero
            };

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options => {
                    options.RequireHttpsMetadata = false;
                    options.SaveToken = true;
                    options.TokenValidationParameters = tokenValidationParameters;
                });

            services.AddAuthorization(options =>
            {
                options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build();
                options.AddPolicy("AdminAccess", policy => policy.RequireClaim("role", "admin"));
            });

            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    builder => builder.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());
            });

            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseAuthentication();            // JWT Authentication
            app.UseMvc();
        }
    }
}

TokenController.cs

namespace JwtWebApplication.Controllers
{
    public class TokenController : Controller
    {
        private readonly IConfiguration configuration;

        public TokenController(IConfiguration configuration)
        {
            this.configuration = configuration;
        }

        [HttpPost]
        [Route("api/token")]
        public IActionResult GetToken([FromBody] TokenRequest tokenRequest)
        {
            if (string.IsNullOrWhiteSpace(tokenRequest.Username) || (tokenRequest.Username != tokenRequest.Password))
            {
                return BadRequest();
            }

            return new ObjectResult(GenerateToken(tokenRequest.Username));
        }

        private string GenerateToken(string username)
        {
            var claims = new Claim[]
            {
                new Claim(ClaimTypes.Name, username),
                new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()),
                new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddDays(1)).ToUnixTimeSeconds().ToString()),
                new Claim(ClaimTypes.Role, "admin"),
                new Claim("role", "admin")
            };

            string issuer = this.configuration.GetSection("TokenAuthentication:Issuer").Value;
            string audience = this.configuration.GetSection("TokenAuthentication:Audience").Value;
            string key = this.configuration.GetSection("TokenAuthentication:Key").Value;

            SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key));
            SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(issuer, audience, claims, null, null, signingCredentials);

            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
}

ValuesController.cs

namespace JwtWebApplication.Controllers
{
    public class ValuesController : Controller
    {
        [AllowAnonymous]
        [HttpGet]
        [Route("api/values")]
        public IEnumerable<string> GetValues()
        {
            return new string[] { "Value 1", "Value 2", "Value 3" };
        }

        [Authorize]
        [HttpGet]
        [Route("api/secretvalues")]
        public IEnumerable<string> GetSecretValues()
        {
            return new string[] { "Secret Value 1", "Secret Value 2", "Secret Value 3" };
        }

        [Authorize(Policy = "AdminAccess")]
        [HttpGet]
        [Route("api/adminsecretvalues")]
        public IEnumerable<string> GetAdminSecretValues()
        {
            return new string[] { "Admin Secret Value 1", "Admin Secret Value 2", "Admin Secret Value 3" };
        }
    }
}

我将声明new Claim(ClaimTypes.Role, "admin")添加到令牌中,我认为这已经足够了,但显然不是。就像在授权过程中没有解压缩一样。但是如果我在ValuesController中调试HttpContext.User对象,我可以看到声明存在,但它根本不起作用。 也许我不明白,但我不知道它是什么。

1 个答案:

答案 0 :(得分:3)

有同样的问题然后找到了解决方案,以防其他人遇到同样的问题。

  

services.AddAuthorization(options =&gt; {       options.AddPolicy(“AdminAccess”,policy =&gt;       {            的 policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);           policy.RequireAuthenticatedUser();           policy.Requirements.Add(new MinimumAgeRequirement());       }); });

添加策略时,也要定义AuthenticationScheme。

以下是您可以了解更多内容的链接

https://docs.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?tabs=aspnetcore2x