.NET Core 中的 JWT 授权——401 错误
Posted
技术标签:
【中文标题】.NET Core 中的 JWT 授权——401 错误【英文标题】:JWT Authorization in .NET Core -- 401 Error 【发布时间】:2019-01-04 18:19:17 【问题描述】:我正在尝试在简单的 UI 和 Web API 之间实现 JWT 身份验证。两者都是 .NET Core 2.0,我使用 Ajax 调用 API 函数。我可以毫无问题地登录,并将 Bearer 令牌传回给我;但是,当我使用 Authorize 装饰 SaveProduct 方法,使用 Ajax 调用它并传递令牌时,它返回 401 Unauthorized。一旦我删除授权,它就可以正常工作。我已经工作了好几天来弄清楚我缺少什么,并创建了我的应用程序的几次迭代,看看这是否会有所帮助,但一直无法弄清楚。我在网上搜索并尝试了许多建议,但仍然无济于事。
如果您有任何见解,我将不胜感激。提前致谢!
这是我的代码:
WEB API -- 启动
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
namespace SportsStoreAngAPI
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.AddCors(options =>
options.AddPolicy("AllowAllOrigins",
builder => builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.Build());
);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
options.TokenValidationParameters = new TokenValidationParameters
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superdooperultrasafeKey#999")),
RequireSignedTokens = false,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "http://localhost:3700",
ValidAudience = "http://localhost:3700"
;
);
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)
app.UseCors("AllowAllOrigins");
app.UseStatusCodePages();
app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc();
WEB API -- 登录控制器
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using SportsStoreAngAPI.Models;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SportsStoreAngAPI.Controllers
[Route("[controller]")]
public class LoginController : Controller
[HttpPost]
public JsonResult Login([FromBody] LoginModel user)
LoginReturnModel l = new LoginReturnModel();
if (user == null)
l.Success = false;
l.Token = null;
if (user.Name == "admin" && user.Password == "secret")
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@345"));
var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);
var tokenOptions = new JwtSecurityToken(
//issuer: "http://localhost:3700",
//audience: "http://localhost:3700",
//claims: new List<Claim>(),
expires: DateTime.Now.AddDays(5),
signingCredentials: signinCredentials
);
var tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions);
l.Success = true;
l.Token = tokenString;
else
l.Success = false;
l.Token = null;
JsonResult jR = new JsonResult(l);
return jR;
WEB API - 产品控制器
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SportsStoreAngAPI.Models;
using System.Collections.Generic;
namespace SportsStoreAngAPI.Controllers
[Produces("application/json")]
[Route("[controller]")]
public class ProductsController : Controller
[HttpGet]
public IEnumerable<Product> GetProducts()
List<Product> p = new List<Product>();
return p;
[HttpPost, Authorize]
public Product SaveProduct([FromBody]Product p)
return p;
前端用户界面
@
ViewData["Title"] = "Home Page";
<button class="btn btn-primary" type="button" onclick="loginAPI()">Login</button>
<div name="puthere" id="puthere"></div>
<button class="btn btn-primary" type="button" onclick="postNewRecord()">Post New Record</button>
<div name="puthere2" id="puthere2"></div>
<script>
$(document).ready(function ()
);
var token = '';
var loginAPI = function ()
var myData =
Name: 'admin',
Password: 'secret'
;
var myDataString = JSON.stringify(myData);
$.ajax(
type: 'POST',
url: 'http://localhost:3700/login',
contentType: 'application/json;charset=utf-8',
dataType: 'json',
data: myDataString,
success: function (results)
$('#puthere').empty();
var html = '';
$.each(results, function (index, value)
html = html + '<p>' + index + ' : ' + value + '</p>';
if (index == 'token')
token = value;
;
);
$('#puthere').append(html);
,
error: function (xhr, textStatus, error)
alert(Error);
alert(xhr.statusText);
alert(textStatus);
alert(error);
);
;
var postNewRecord = function ()
var myData =
Id: '0',
Name: 'Soccer Ball',
Category: 'Sports',
Description: 'Round ball for playing the beautiful game',
Price: '13.75'
;
var myDataString = JSON.stringify(myData);
$.ajax(
type: 'POST',
url: 'http://localhost:3700/products',
contentType: 'application/json;charset=utf-8',
dataType: 'json',
data: myDataString,
beforeSend: function (xhr)
xhr.setRequestHeader('Authorization', token)
,
success: function()
alert('Saved successfully!');
,
error: function ()
alert('Something went very wrong!');
);
;
</script>
【问题讨论】:
【参考方案1】:编辑:在您的 Startup-Class 中,您定义了一个与生成令牌时使用的密钥不同的密钥。它们也必须相同。我建议您阅读一些有关 JWT 及其工作原理的信息 here。
所以我注意到的第一件事是您从后端生成的令牌中删除了颁发者。您必须定义它们,因为您还在 Startup-Class 中设置了它们。
其次,您的 ajax 请求标头必须这样设置:
xhr.setRequestHeader('Authorization', 'Bearer ' + token)
您必须在 headers-value 中定义授权类型。
【讨论】:
我将 Bearer 添加到 setRequestHeader 调用中,并从后端的发行者那里删除了评论。仍然在响应头中得到这个:WWW-Authenticate: Bearer error="invalid_token", error_description="签名无效" 我更新了答案。您应该确保您配置的令牌必须提供,否则身份验证将失败。 成功了!我在一个地方改变了它,但在另一个地方没有改变。我还需要取消注释观众才能使其正常工作。感谢您的帮助! 很高兴它有帮助。以上是关于.NET Core 中的 JWT 授权——401 错误的主要内容,如果未能解决你的问题,请参考以下文章
将 API 迁移到 .net Core 3 时出现 JWT 401 未经授权的错误
ASP.NET Core 5.0 JWT 身份验证总是抛出 HTTP 401 代码
.NET Core 2.1 中的 HttpContext.GetTokenAsync 无法检索 JWT
每当我发送包含 Bearer 令牌的请求时,ASP.Net Core API 总是返回 401 未授权