Asp.net core 使用Api密钥的Web Api承载JWT令牌身份验证在令牌身份验证成功后的连续调用中失败
我创建了一个MVC核心API,它使用API密钥对用户进行身份验证。成功验证后,它会发回一个JWT令牌,用于任何后续请求。 我可以使用有效的api密钥成功地进行身份验证,并获得一个令牌作为响应。然后我可以使用这个令牌发出请求,但下一个请求失败。 在我的实际应用程序中,消费者是一个MVC核心站点,直到现在我还没有注意到这个问题,因为在每个MVC控制器操作中,我都调用一个api操作,但是现在我需要在同一个MVC操作上一个接一个地调用两个api操作,第二个操作失败了,我无法理解为什么 我在一个示例web api和控制台应用程序中复制了我的问题 这是MVC核心API端点验证API密钥并生成jwt令牌的代码:Asp.net core 使用Api密钥的Web Api承载JWT令牌身份验证在令牌身份验证成功后的连续调用中失败,asp.net-core,asp.net-core-mvc,Asp.net Core,Asp.net Core Mvc,我创建了一个MVC核心API,它使用API密钥对用户进行身份验证。成功验证后,它会发回一个JWT令牌,用于任何后续请求。 我可以使用有效的api密钥成功地进行身份验证,并获得一个令牌作为响应。然后我可以使用这个令牌发出请求,但下一个请求失败。 在我的实际应用程序中,消费者是一个MVC核心站点,直到现在我还没有注意到这个问题,因为在每个MVC控制器操作中,我都调用一个api操作,但是现在我需要在同一个MVC操作上一个接一个地调用两个api操作,第二个操作失败了,我无法理解为什么 我在一个示例web
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using PureHub.Services.Models.Valid8.Authentication;
namespace BugApiJwt.Controllers
{
[Authorize]
[Route("v1/[controller]")]
public class AuthenticationController : ControllerBase
{
[AllowAnonymous]
[HttpPost("[action]")]
public virtual async Task<IActionResult> Token([FromBody] ApiLoginRequest model)
{
if (model != null)
{
if (model.ApiKey == "VdPfwrL+mpRHKgzAIm9js7e/J9AbJshoPgv1nIZiat22R")
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")),
new Claim(JwtRegisteredClaimNames.Iat,
new DateTimeOffset(DateTime.UtcNow).ToUniversalTime().ToUnixTimeSeconds().ToString(),
ClaimValueTypes.Integer64)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("FTTaIMmkh3awD/4JF0iHgAfNiB6/C/gFeDdrKU/4YG1ZK36o16Ja4wLO+1Qft6yd+heHPRB2uQqXd76p5bXXPQ=="));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "http://localhost:58393/",
audience: "http://localhost:58393/",
claims: claims,
expires: DateTime.UtcNow.AddMinutes(30),
signingCredentials: creds);
return Ok(new ApiLoginResponse
{
Token = new JwtSecurityTokenHandler().WriteToken(token),
Expiration = token.ValidTo
});
}
}
return BadRequest();
}
}
}
这是我正在测试的控制台应用程序:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace BugApiJwt.Console
{
public class Program
{
private const string ApiKey = "VdPfwrL+mpRHKgzAIm9js7e/J9AbJshoPgv1nIZiat22R";
private const string BaseAddress = "http://localhost:58393/";
private static HttpClient _client = new HttpClient();
private static string _realToken = string.Empty;
private static void Main()
{
_client = new HttpClient
{
BaseAddress = new Uri(BaseAddress)
};
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Works
System.Console.WriteLine("Call GetOne");
var getOne = Get().GetAwaiter().GetResult();
System.Console.WriteLine(getOne);
// Fails
System.Console.WriteLine("Call GetAll");
var getTwo = GetAll().GetAwaiter().GetResult();
System.Console.WriteLine(getTwo);
System.Console.WriteLine("All Finished. Press Enter to exit");
System.Console.ReadLine();
}
private static async Task<string> GetAuthenticationToken()
{
const string resource = "v1/authentication/token";
if (!string.IsNullOrEmpty(_realToken)){return _realToken;}
var loginRequest = new ApiLoginRequest{ApiKey = ApiKey};
var httpResponseMessage = await _client.PostAsync(resource, ObjectToJsonContent(loginRequest)).ConfigureAwait(false);
if (httpResponseMessage.IsSuccessStatusCode)
{
var content = await httpResponseMessage.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<ApiLoginResponse>(content);
_realToken = obj.Token;
return obj.Token;
}
throw new Exception("Token is null");
}
public static async Task<string> Get()
{
var resource = "v1/values/1";
var token = await GetAuthenticationToken();
_client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {token}");
var httpResponseMessage = await _client.GetAsync(resource);
System.Console.WriteLine(httpResponseMessage.RequestMessage.Headers.Authorization);
System.Console.WriteLine(httpResponseMessage.Headers.WwwAuthenticate);
var content = await httpResponseMessage.Content.ReadAsStringAsync();
return content;
}
public static async Task<string> GetAll()
{
var resource = "v1/values";
var token = await GetAuthenticationToken();
_client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {token}");
var httpResponseMessage = await _client.GetAsync(resource);
System.Console.WriteLine(httpResponseMessage.RequestMessage.Headers.Authorization);
System.Console.WriteLine(httpResponseMessage.Headers.WwwAuthenticate);
var content = await httpResponseMessage.Content.ReadAsStringAsync();
return content;
}
private static StringContent ObjectToJsonContent<T>(T objectToPost) where T : class, new()
{
var tJson = JsonConvert.SerializeObject(objectToPost,
Formatting.Indented, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
return new StringContent(tJson, Encoding.UTF8, "application/json");
}
}
public class ApiLoginRequest
{
public string ApiKey { get; set; }
}
public class ApiLoginResponse
{
public string Token { get; set; }
public DateTime Expiration { get; set; }
}
}
使用系统;
使用System.Net.Http;
使用System.Net.Http.Header;
使用系统文本;
使用System.Threading.Tasks;
使用Newtonsoft.Json;
使用Newtonsoft.Json.Serialization;
名称空间BugApiJwt.Console
{
公共课程
{
private const string ApiKey=“VdPfwrL+mpRHKgzAIm9js7e/J9AbJshoPgv1nIZiat22R”;
专用常量字符串基地址=”http://localhost:58393/";
私有静态HttpClient _client=new HttpClient();
私有静态字符串_realToken=string.Empty;
私有静态void Main()
{
_client=新的HttpClient
{
BaseAddress=新Uri(BaseAddress)
};
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);
//工作
System.Console.WriteLine(“调用GetOne”);
var getOne=Get().GetAwaiter().GetResult();
系统控制台写入线(getOne);
//失败
System.Console.WriteLine(“调用GetAll”);
var getTwo=GetAll().GetAwaiter().GetResult();
System.Console.WriteLine(getTwo);
System.Console.WriteLine(“全部完成。按Enter键退出”);
System.Console.ReadLine();
}
私有静态异步任务GetAuthenticationToken()
{
const string resource=“v1/authentication/token”;
如果(!string.IsNullOrEmpty(_realToken)){return\u realToken;}
var loginRequest=new ApiLoginRequest{ApiKey=ApiKey};
var httpResponseMessage=await_client.postsync(资源,ObjectToJsonContent(loginRequest)).ConfigureAwait(false);
if(httpResponseMessage.IsSuccessStatusCode)
{
var content=await httpResponseMessage.content.ReadAsStringAsync();
var obj=JsonConvert.DeserializeObject(内容);
_realToken=obj.Token;
返回对象令牌;
}
抛出新异常(“令牌为空”);
}
公共静态异步任务Get()
{
var resource=“v1/values/1”;
var token=等待GetAuthenticationToken();
_client.DefaultRequestHeaders.TryAddWithoutValidation(“Authorization”、$“Bearer{token}”);
var httpResponseMessage=await_client.GetAsync(资源);
System.Console.WriteLine(httpResponseMessage.RequestMessage.Headers.Authorization);
System.Console.WriteLine(httpResponseMessage.Headers.wwwaauthenticate);
var content=await httpResponseMessage.content.ReadAsStringAsync();
返回内容;
}
公共静态异步任务GetAll()
{
var resource=“v1/values”;
var token=等待GetAuthenticationToken();
_client.DefaultRequestHeaders.TryAddWithoutValidation(“Authorization”、$“Bearer{token}”);
var httpResponseMessage=await_client.GetAsync(资源);
System.Console.WriteLine(httpResponseMessage.RequestMessage.Headers.Authorization);
System.Console.WriteLine(httpResponseMessage.Headers.wwwaauthenticate);
var content=await httpResponseMessage.content.ReadAsStringAsync();
返回内容;
}
私有静态StringContent ObjectToJsonContent(T objectToPost),其中T:class,new()
{
var tJson=JsonConvert.SerializeObject(objectToPost,
格式化。缩进,新JsonSerializerSettings
{
NullValueHandling=NullValueHandling.Ignore,
ContractResolver=新的CamelCasePropertyNamesContractResolver()
});
返回新的StringContent(tJson,Encoding.UTF8,“application/json”);
}
}
公共类ApiLoginRequest
{
公共字符串ApiKey{get;set;}
}
公共类蜂群应答器
{
公共字符串标记{get;set;}
公共日期时间过期{get;set;}
}
}
关于第二次呼叫失败的原因有什么帮助吗
web api输出窗口中显示的错误消息为:
持票人未经身份验证。失败消息:没有可用于令牌的SecurityTokenValidator:2.2.2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 JBGFPBxMVCM9SzSi6IkFkBwLuaxn0cmf0b3iiIllcYOj1mTawnJQ4ndmSiMV4Ci6mTuxDa2nJy0mDov2xVy2FsAg9Zddo0ndm2MciSiMF1Zci6imh0Dh6Sb2HbGHVC3Q6ndQznJaiFQ.wJ86UT2DMBdRdCnxU2KwXeqQQgKivxIvxZc
它不起作用,因为这段代码
tryadd没有验证(“授权”,$“承载{t
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 BugApiJwt
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "http://localhost:58393/",
ValidAudience = "http://localhost:58393/",
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("FTTaIMmkh3awD/4JF0iHgAfNiB6/C/gFeDdrKU/4YG1ZK36o16Ja4wLO+1Qft6yd+heHPRB2uQqXd76p5bXXPQ==")),
};
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
}
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace BugApiJwt.Console
{
public class Program
{
private const string ApiKey = "VdPfwrL+mpRHKgzAIm9js7e/J9AbJshoPgv1nIZiat22R";
private const string BaseAddress = "http://localhost:58393/";
private static HttpClient _client = new HttpClient();
private static string _realToken = string.Empty;
private static void Main()
{
_client = new HttpClient
{
BaseAddress = new Uri(BaseAddress)
};
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Works
System.Console.WriteLine("Call GetOne");
var getOne = Get().GetAwaiter().GetResult();
System.Console.WriteLine(getOne);
// Fails
System.Console.WriteLine("Call GetAll");
var getTwo = GetAll().GetAwaiter().GetResult();
System.Console.WriteLine(getTwo);
System.Console.WriteLine("All Finished. Press Enter to exit");
System.Console.ReadLine();
}
private static async Task<string> GetAuthenticationToken()
{
const string resource = "v1/authentication/token";
if (!string.IsNullOrEmpty(_realToken)){return _realToken;}
var loginRequest = new ApiLoginRequest{ApiKey = ApiKey};
var httpResponseMessage = await _client.PostAsync(resource, ObjectToJsonContent(loginRequest)).ConfigureAwait(false);
if (httpResponseMessage.IsSuccessStatusCode)
{
var content = await httpResponseMessage.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<ApiLoginResponse>(content);
_realToken = obj.Token;
return obj.Token;
}
throw new Exception("Token is null");
}
public static async Task<string> Get()
{
var resource = "v1/values/1";
var token = await GetAuthenticationToken();
_client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {token}");
var httpResponseMessage = await _client.GetAsync(resource);
System.Console.WriteLine(httpResponseMessage.RequestMessage.Headers.Authorization);
System.Console.WriteLine(httpResponseMessage.Headers.WwwAuthenticate);
var content = await httpResponseMessage.Content.ReadAsStringAsync();
return content;
}
public static async Task<string> GetAll()
{
var resource = "v1/values";
var token = await GetAuthenticationToken();
_client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {token}");
var httpResponseMessage = await _client.GetAsync(resource);
System.Console.WriteLine(httpResponseMessage.RequestMessage.Headers.Authorization);
System.Console.WriteLine(httpResponseMessage.Headers.WwwAuthenticate);
var content = await httpResponseMessage.Content.ReadAsStringAsync();
return content;
}
private static StringContent ObjectToJsonContent<T>(T objectToPost) where T : class, new()
{
var tJson = JsonConvert.SerializeObject(objectToPost,
Formatting.Indented, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
return new StringContent(tJson, Encoding.UTF8, "application/json");
}
}
public class ApiLoginRequest
{
public string ApiKey { get; set; }
}
public class ApiLoginResponse
{
public string Token { get; set; }
public DateTime Expiration { get; set; }
}
}