Asp.net core 使用Api密钥的Web 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

我创建了一个MVC核心API,它使用API密钥对用户进行身份验证。成功验证后,它会发回一个JWT令牌,用于任何后续请求。 我可以使用有效的api密钥成功地进行身份验证,并获得一个令牌作为响应。然后我可以使用这个令牌发出请求,但下一个请求失败。 在我的实际应用程序中,消费者是一个MVC核心站点,直到现在我还没有注意到这个问题,因为在每个MVC控制器操作中,我都调用一个api操作,但是现在我需要在同一个MVC操作上一个接一个地调用两个api操作,第二个操作失败了,我无法理解为什么

我在一个示例web api和控制台应用程序中复制了我的问题

这是MVC核心API端点验证API密钥并生成jwt令牌的代码:

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; }
    }
}