ASP.NET 核心 JWTBearer身份验证未正确进行身份验证/授权



我遇到的问题是当我在TokenController中使用signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("secret")), SecurityAlgorithms.HmacSha256)时,我在var encoded_token = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler().WriteToken(token);得到500 Internal Server Error

我相信这可能与适当的证书有关。

当我删除该行并转到http://localhost:61571/api/Users时,我得到一个401 Unauthorized状态代码。 当我将其插入在线解码器时,创建的 JWT 似乎工作正常。

所以我的问题是:

  1. 为什么JwtSecurityTokenHandler().WriteToken(token);给我一个 500 内部服务器错误?
  2. 为什么我会收到 401 未授权代码?

我正在使用带有 ASP.NET 酷1.1的VS2017。 这一切都在VS2017的IIS Express上运行。

启动.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using ToDoApi.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System;
namespace ToDoApi
{
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();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ToDoApi.Data.ApplicationDbContext>(opt => opt.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddSingleton<IUserService, UserService>();
// Add framework services.
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, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
env.EnvironmentName = EnvironmentName.Development;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
}

var keyAsBytes = Encoding.ASCII.GetBytes("secret");
var options = new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("secret")),
ValidateIssuerSigningKey = true,
ValidAudience = "http://localhost:61571",
ValidateAudience = true,
ValidIssuer = "http://localhost:61571",
ValidateIssuer = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
}
};
app.UseJwtBearerAuthentication(options);
app.UseMvc();
}
}
}

令牌控制器.cs

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using ToDoApi.Models;
namespace ToDoApi.Controllers
{
[Produces("application/json")]
[Route("api/[controller]")]
public class TokenController : Controller
{
[HttpPost]
public IActionResult Token([FromBody] User model)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
var user = new User { ID = 1, Username = "username", Password = "password" };//await _userManager.FindByNameAsync(model.Email);
//if (user == null || _passwordHasher.VerifyHashedPassword(user, user.PasswordHash, model.Password) != PasswordVerificationResult.Success)
//{
//    return BadRequest();
// }
var claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub, "username"),
new Claim(JwtRegisteredClaimNames.Jti, "40fdb6d4-1ea5-49af-9fcc-edb9e8d18dd5"),
new Claim(JwtRegisteredClaimNames.Iat, new DateTimeOffset(DateTime.UtcNow).ToUniversalTime().ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
};
var token = new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(
issuer: "http://localhost:61571",
audience: "http://localhost:61571",
claims: claims,
notBefore: DateTime.UtcNow,
expires: DateTime.UtcNow.AddMinutes(10),
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("secret")), SecurityAlgorithms.HmacSha256)
);
var encoded_token = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler().WriteToken(token);
return Ok(new
{
token = encoded_token,
expiration = token.ValidTo
});
}
}
}

用户控制器.cs

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ToDoApi.Models;
using ToDoApi.Services;
using Microsoft.AspNetCore.Authorization;
using System.IdentityModel.Tokens.Jwt;
namespace ToDoApi.Controllers
{
[Produces("application/json")]
[Route("api/[controller]")]
public class UsersController : Controller
{
private readonly IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
// GET: api/Users
[Authorize]
[HttpGet]
public IEnumerable<User> GetUsers()
{
return _userService.ListAll();
}
}
}

您获得 500 代码的原因可能是您使用了太短的密钥来HMACSHA256。尝试使用至少 128 位大小(16 个符号(的字符串。

对于 401 代码,这取决于。如果在尝试生成令牌时收到 500 错误,则在授权标头中使用什么令牌?

401的另一个棘手原因可能是您正在使用Bearer授权以及Cookie和身份框架。在这种情况下,您需要在UseIdentity之前呼叫UseJwtBearerAuthentication。但从您提供的代码示例中,您似乎不使用 Identity。

最新更新