Asp.net mvc .NET内核中的JWT授权--401错误
我试图在一个简单的UI和Web API之间实现JWT身份验证。两者都是.NETCore2.0,我使用Ajax调用API函数。我可以登录没有任何问题,它传递给我的持有人令牌;但是,当我用Authorize修饰SaveProduct方法,用Ajax调用它,并传递令牌时,它返回401。我一卸下电源,它就可以正常工作了。我花了好几天的时间来找出我遗漏了什么,并对我的应用程序进行了多次迭代,看看这是否会有所帮助,但一直没能找到答案。我在网上搜索了很多建议,但都没有结果 如果您有任何见解,我将不胜感激。提前谢谢 这是我的密码: WEB API—启动Asp.net mvc .NET内核中的JWT授权--401错误,asp.net-mvc,asp.net-core,jwt,asp.net-ajax,Asp.net Mvc,Asp.net Core,Jwt,Asp.net Ajax,我试图在一个简单的UI和Web API之间实现JWT身份验证。两者都是.NETCore2.0,我使用Ajax调用API函数。我可以登录没有任何问题,它传递给我的持有人令牌;但是,当我用Authorize修饰SaveProduct方法,用Ajax调用它,并传递令牌时,它返回401。我一卸下电源,它就可以正常工作了。我花了好几天的时间来找出我遗漏了什么,并对我的应用程序进行了多次迭代,看看这是否会有所帮助,但一直没能找到答案。我在网上搜索了很多建议,但都没有结果 如果您有任何见解,我将不胜感激。提前
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;
}
}
}
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;
}
}
}
使用Microsoft.AspNetCore.Mvc;
使用Microsoft.IdentityModel.Tokens;
使用SportsStoreAngAPI.Models;
使用制度;
使用System.Collections.Generic;
使用System.IdentityModel.Tokens.Jwt;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
命名空间sportstoreangapi.Controllers
{
[路线(“[控制器]”)]
公共类登录控制器:控制器
{
[HttpPost]
公共JsonResult登录([FromBody]LoginModel用户)
{
LoginReturnModel l=新的LoginReturnModel();
if(user==null)
{
l、 成功=错误;
l、 令牌=null;
}
if(user.Name==“admin”&&user.Password==“secret”)
{
var secretKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(“superSecretKey@345"));
var signinCredentials=新的签名凭证(secretKey,SecurityAlgorithms.HmacSha256);
var tokenOptions=新的JwtSecurityToken(
//发行人:“http://localhost:3700",
//听众:“http://localhost:3700",
//声明:新列表(),
过期日期:DateTime.Now.AddDays(5),
签名凭据:签名凭据
);
var tokenString=new JwtSecurityTokenHandler().WriteToken(tokenOptions);
l、 成功=真实;
l、 令牌=令牌字符串;
}
其他的
{
l、 成功=错误;
l、 令牌=null;
}
JsonResult jR=新的JsonResult(l);
返回jR;
}
}
}
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;
}
}
}
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;
}
}
}
使用Microsoft.AspNetCore.Authorization;
使用Microsoft.AspNetCore.Mvc;
使用SportsStoreAngAPI.Models;
使用System.Collections.Generic;
命名空间sportstoreangapi.Controllers
{
[产生(“应用程序/json”)]
[路线(“[控制器]”)]
公共类产品控制器:控制器
{
[HttpGet]
公共IEnumerable GetProducts()
{
列表p=新列表();
返回p;
}
[HttpPost,授权]
公共产品SaveProduct([FromBody]产品p)
{
返回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>
@{
ViewData[“Title”]=“主页”;
}
登录
发布新记录
$(文档).ready(函数(){
});
var标记=“”;
var loginAPI=函数(){
var myData=
{
名称:'管理员',
密码:“机密”
};
var myDataString=JSON.stringify(myData);
$.ajax({
键入:“POST”,
网址:'http://localhost:3700/login',
contentType:'application/json;charset=utf-8',
数据类型:“json”,
数据:myDataString,
成功:功能(结果){
$('#puthere').empty();
var html='';
$.each(结果、函数(索引、值){
html=html+''+index+':'+value+'';
如果(索引=='token'){
代币=价值;
};
});
$('#puthere').append(html);
},
错误:函数(xhr、textStatus、error){
警报(错误);
警报(xhr.statusText);
警报(文本状态);
警报(错误);
}
});
};
var postNewRecord=函数(){
var myData=
{
Id:'0',
名称:‘足球’,
类别:"体育",,
描述:“玩漂亮游戏的圆球”,
价格:'13.75'
};
var myDataString=JSON.stringify(myData);
$.ajax({
键入:“POST”,
网址:'http://localhost:3700/products',
contentType:'application/json;charset=utf-8',
数据类型:“json”,
数据:myDataString,
发送前:函数(xhr){
xhr.setRequestHeader('授权',令牌)
},
成功:函数(){
警报(“保存成功!”);
},
错误:函数(){
警惕(“出了很大的问题!”);
}
});
};
编辑:在启动类中,您定义了一个与生成令牌时使用的密钥不同的密钥。它们也必须是相同的。我建议你读一点关于JWT及其工作原理的书
所以我注意到的第一件事是,您从后端生成的令牌中删除了颁发者。您必须定义它们,因为您还可以在Startup类中设置它们
其次,您的ajax请求头必须如下设置:
xhr.setRequestHeader('Authorization', 'Bearer ' + token)
您必须在headers值中定义授权类型。编辑:在启动类中,您定义了一个与生成令牌时使用的密钥不同的密钥。它们也必须是相同的