C# ASP.NET Web Api 2在异常时自动添加标头

C# ASP.NET Web Api 2在异常时自动添加标头,c#,asp.net,asp.net-web-api,asp.net-core-webapi,C#,Asp.net,Asp.net Web Api,Asp.net Core Webapi,我目前正在跟踪 实现Jwt刷新令牌。目前,我正在尝试添加一个名为tokenexpired的头,当我在响应API请求时收到一个特定的异常时,“true” 在本教程中,本节介绍如何在Startup.cs中执行此操作 public void ConfigureServices(IServiceCollection services) { services.AddMvc(); //... services.AddAuthentication(options =>

我目前正在跟踪 实现Jwt刷新令牌。目前,我正在尝试添加一个名为tokenexpired的头,当我在响应API请求时收到一个特定的异常时,“true”

在本教程中,本节介绍如何在Startup.cs中执行此操作

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    //...

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = "bearer";
        options.DefaultChallengeScheme = "bearer";
    }).AddJwtBearer("bearer", options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = false,
            ValidateIssuer = false,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("the server key used to sign the JWT token is here, use more than 16 chars")),
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero //the default for this setting is 5 minutes
        };
        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                {
                    context.Response.Headers.Add("Token-Expired", "true");
                }
                return Task.CompletedTask;
            }
        };
    });
}
问题是我使用的是ASP.NET Web Api 2,而不是.NET core 2.1。如何将此代码添加到我的代码中?我认为可行的一种方法是,我可以将其添加到我的TokenValidation类中,但我不知道如何这样做:

public class TokenValidationHandler : DelegatingHandler
{
    private static bool RetrieveToken(HttpRequestMessage request, out string token)
    {
        token = null;
        IEnumerable<string> authHeaders;
        if (!request.Headers.TryGetValues("Authorization", out authHeaders) || authHeaders.Count() > 1)
        {
            return false;
        }
        var bearerToken = authHeaders.ElementAt(0);
        token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
        return true;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpStatusCode statusCode;
        string token;
        //determine whether a jwt exists or not
        if (!RetrieveToken(request, out token))
        {
            statusCode = HttpStatusCode.Unauthorized;
            //allow requests with no token - whether a action method needs an authentication can be set with the claimsauthorization attribute
            return base.SendAsync(request, cancellationToken);
        }

        try
        {
            const string sec = HostConfig.SecurityKey;
            var now = DateTime.UtcNow;
            var securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));


            SecurityToken securityToken;
            JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
            TokenValidationParameters validationParameters = new TokenValidationParameters()
            {
                ValidAudience = HostConfig.Audience,
                ValidIssuer = HostConfig.Issuer,
                //Set false to ignore expiration date
                ValidateLifetime = false,
                ValidateIssuerSigningKey = true,
                LifetimeValidator = this.LifetimeValidator,
                IssuerSigningKey = securityKey
            };
            //extract and assign the user of the jwt
            Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
            HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);

            return base.SendAsync(request, cancellationToken);
        }
        catch (SecurityTokenValidationException e)
        {
            statusCode = HttpStatusCode.Unauthorized;
        }
        catch (Exception ex)
        {
            statusCode = HttpStatusCode.InternalServerError;
        }
        return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(statusCode) { });
    }

    public bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
    {
        if (expires != null)
        {
            if (DateTime.UtcNow < expires) return true;
        }
        return false;
    }
}
公共类TokenValidationHandler:DelegatingHandler
{
私有静态bool RetrieveToken(HttpRequestMessage请求,输出字符串令牌)
{
令牌=null;
IEnumerable AuthHeader;
如果(!request.Headers.TryGetValues(“Authorization”,out authHeaders)| | authHeaders.Count()>1)
{
返回false;
}
var bearerToken=authHeaders.ElementAt(0);
token=bearerToken.StartsWith(“Bearer”)?bearerToken.Substring(7):bearerToken;
返回true;
}
受保护的覆盖任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
HttpStatusCode状态码;
字符串标记;
//确定jwt是否存在
如果(!RetrieveToken(请求,输出令牌))
{
statusCode=HttpStatusCode.未经授权;
//允许不带令牌的请求-可以使用claimsauthorization属性设置操作方法是否需要身份验证
返回base.sendaync(请求、取消令牌);
}
尝试
{
const string sec=HostConfig.SecurityKey;
var now=DateTime.UtcNow;
var securityKey=new-SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));
SecurityToken SecurityToken;
JwtSecurityTokenHandler=新的JwtSecurityTokenHandler();
TokenValidationParameters validationParameters=新的TokenValidationParameters()
{
ValidAudience=HostConfig.accounter,
ValidIssuer=HostConfig.Issuer,
//设置false忽略到期日期
ValidateLifetime=false,
ValidateSuersigningKey=true,
LifetimeValidator=this.LifetimeValidator,
IssuerSigningKey=安全密钥
};
//提取并分配jwt的用户
Thread.CurrentPrincipal=handler.ValidateToken(令牌、validationParameters、out securityToken);
HttpContext.Current.User=handler.ValidateToken(令牌、validationParameters、out securityToken);
返回base.sendaync(请求、取消令牌);
}
捕获(SecurityTokenValidationException e)
{
statusCode=HttpStatusCode.未经授权;
}
捕获(例外情况除外)
{
statusCode=HttpStatusCode.InternalServerError;
}
返回Task.Factory.StartNew(()=>newhttpresponsemessage(statusCode){});
}
public bool LifetimeValidator(DateTime?notBefore、DateTime?expires、SecurityToken SecurityToken、TokenValidationParameters validationParameters)
{
如果(过期!=null)
{
if(DateTime.UtcNow
您还需要先安装Microsoft.Owin.Host.SystemWeb包。然后创建一个名为Startup.cs的类

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    //...

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = "bearer";
        options.DefaultChallengeScheme = "bearer";
    }).AddJwtBearer("bearer", options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = false,
            ValidateIssuer = false,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("the server key used to sign the JWT token is here, use more than 16 chars")),
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero //the default for this setting is 5 minutes
        };
        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                {
                    context.Response.Headers.Add("Token-Expired", "true");
                }
                return Task.CompletedTask;
            }
        };
    });
}
这对你有帮助

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      //
   }
   public void ConfigureServices(IServiceCollection services)
   {
    services.AddMvc();
    //...

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = "bearer";
        options.DefaultChallengeScheme = "bearer";
    }).AddJwtBearer("bearer", options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = false,
            ValidateIssuer = false,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("the server key used to sign the JWT token is here, use more than 16 chars")),
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero //the default for this setting is 5 minutes
        };
        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                {
                    context.Response.Headers.Add("Token-Expired", "true");
                }
                return Task.CompletedTask;
            }
        };
    });
}
}
除此之外,如果启动类不在默认名称空间中,请在
区域中添加一个web配置行,如:

要使用
ConfigureServices
方法,您需要有内置依赖项注入,该方法仅在ASP.NET Core中可用。您需要使用第三方IoC容器,例如-

用于Web API的Autofac

尼尼特

为此,请访问下面的库

Microsoft.Extensions.DependencyInjection


请再添加一个SecurityTokenExpiredException捕获块以捕获令牌过期错误,并在捕获块内添加响应头,如下所示

public class TokenValidationHandler : DelegatingHandler
{
    private static bool RetrieveToken(HttpRequestMessage request, out string token)
    {
        token = null;
        IEnumerable<string> authHeaders;
        if (!request.Headers.TryGetValues("Authorization", out authHeaders) || authHeaders.Count() > 1)
        {
            return false;
        }
        var bearerToken = authHeaders.ElementAt(0);
        token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
        return true;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpResponseMessage response = new HttpResponseMessage();
        string token;
        //determine whether a jwt exists or not
        if (!RetrieveToken(request, out token))
        {
            response.StatusCode = HttpStatusCode.Unauthorized;
            //allow requests with no token - whether a action method needs an authentication can be set with the claimsauthorization attribute
            return base.SendAsync(request, cancellationToken);
        }

        try
        {
            const string sec = HostConfig.SecurityKey;
            var now = DateTime.UtcNow;
            var securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));


            SecurityToken securityToken;
            JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
            TokenValidationParameters validationParameters = new TokenValidationParameters()
            {
                ValidAudience = HostConfig.Audience,
                ValidIssuer = HostConfig.Issuer,
                //Set false to ignore expiration date
                ValidateLifetime = false,
                ValidateIssuerSigningKey = true,
                LifetimeValidator = this.LifetimeValidator,
                IssuerSigningKey = securityKey
            };
            //extract and assign the user of the jwt
            Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
            HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);

            return base.SendAsync(request, cancellationToken);
        }
        catch (SecurityTokenExpiredException e)
        {
            var expireResponse = base.SendAsync(request, cancellationToken).Result;
            response.Headers.Add("Token-Expired", "true");
            response.StatusCode = HttpStatusCode.Unauthorized;

        }
        catch (SecurityTokenValidationException e)
        {
            response.StatusCode = HttpStatusCode.Unauthorized;
        }
        catch (Exception ex)
        {
            response.StatusCode = HttpStatusCode.InternalServerError;
        }
        return Task<HttpResponseMessage>.Factory.StartNew(() => response);
    }

    public bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
    {
        if (expires != null)
        {
            if (DateTime.UtcNow < expires) return true;
        }
        return false;
    }


}
公共类TokenValidationHandler:DelegatingHandler
{
私有静态bool RetrieveToken(HttpRequestMessage请求,输出字符串令牌)
{
令牌=null;
IEnumerable AuthHeader;
如果(!request.Headers.TryGetValues(“Authorization”,out authHeaders)| | authHeaders.Count()>1)
{
返回false;
}
var bearerToken=authHeaders.ElementAt(0);
token=bearerToken.StartsWith(“Bearer”)?bearerToken.Substring(7):bearerToken;
返回true;
}
受保护的覆盖任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
HttpResponseMessage response=新的HttpResponseMessage();
字符串标记;
//确定jwt是否存在
如果(!RetrieveToken(请求,输出令牌))
{
response.StatusCode=HttpStatusCode.Unauthorized;
//允许不带令牌的请求-可以使用claimsauthorization属性设置操作方法是否需要身份验证
返回base.sendaync(请求、取消令牌);
}
尝试
{
const string sec=HostConfig.SecurityKey;
var now=DateTime.UtcNow;
var securityKey=new-SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));
SecurityToken SecurityToken;
JwtSecurityTokenHandler=新的JwtSecurityTokenHandler();
TokenValidationParameters validationParameters=新的TokenValidationParameters()
{
ValidAudience=HostConfig.accounter,
ValidIssuer=HostConfig.Issuer,
//设置false忽略到期日期
ValidateLifetime=false,
ValidateSuersigningKey=tru