邮递员的JWT令牌从未命中具有Authorize属性的控制器

时间:2019-01-29 05:56:27

标签: asp.net-web-api jwt asp.net-core-2.0 bearer-token

试图了解JWT如何用于asp.net核心应用程序。我使用ASP.NET MVC Core应用程序模板。 enter image description here

我的StartUp.cs包含JWT令牌的配置:

 public class Startup
{
     // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();
        services.AddAuthentication(sharedOptions =>
        {
            sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = Configuration["Jwt:Issuer"],
                ValidAudience = Configuration["Jwt:Issuer"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
            };

            //options.EventsType = typeof(AuthenticateCustomEvent);
        });
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

        // In production, the React files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/build";
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseAuthentication();
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSpaStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseReactDevelopmentServer(npmScript: "start");
            }
        });
    }
}

我的登录控制器包含代码,该代码可在成功验证用户后返回令牌,这将如下所示返回令牌

enter image description here

一旦我收到令牌,我便会调用一个带有[Authorize]属性的控制器,并使用来自PostMan的不记名令牌对该控制器进行调用,而该控制器永远不会受到攻击?我想念什么吗?

1 个答案:

答案 0 :(得分:0)

我下面的解决方案有些不同,但是此解决方案将帮助您处理自定义身份验证实现,您可以为不同类型的用户实现不同类型的auth。您需要在API项目下创建一个AuthorizationRequiredAttribute类,该类将继承 ActionFilterAttribute 类以过滤每个API请求。您可以过滤所有HTTP方法(GET,POST,PUT,DELETE等),并可以为特定的HTTP方法实现自己的授权逻辑。

ActionFilterAttribute.cs

using BillSyatemCore.Common.Constants;
using BillSyatemCore.Services.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net;
using System.Net.Http;

namespace BillSyatemCore.Handlers
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
    public class AuthorizationRequiredAttribute : ActionFilterAttribute
    {
        private IConfiguration _config;
        public AuthorizationRequiredAttribute(IConfiguration config)
        {
            _config = config;
        }
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            try
            {
                if (context.HttpContext.Request.Headers.ContainsKey(Constants.HttpHeaders.Token))
                {
                    var handler = new JwtSecurityTokenHandler();
                    var token = handler.ReadToken(context.HttpContext.Request.Headers[Constants.HttpHeaders.Token])
                        as JwtSecurityToken;
                    var expireDate = Convert.ToDateTime(token.Claims.First(claim => claim.Type == Constants.JwtClaims.ExpiresOn).Value);
                    if (context.HttpContext.Request.Method == WebRequestMethods.Http.Get)
                    {
                        if (expireDate < DateTime.Now)
                        {
                            context.Result = new UnauthorizedResult();
                        }
                    }
                    else
                    {

                        //You may filter post,put,delete etc request here.  
                    }
                }
                else
                {
                    context.Result = new NotFoundResult();
                }
            }
            catch (Exception ex)
            {
                context.Result = new BadRequestResult();
            }
            base.OnActionExecuting(context);
        }
    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    //JWT
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = Configuration["Jwt:Issuer"],
            ValidAudience = Configuration["Jwt:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
        };
    });
    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials()
        .Build());
    });

}

Controller.cs

using BillSyatemCore.Models.Authentication;
using BillSystemCore.Transporter;
using Microsoft.AspNetCore.Mvc;

namespace TestProject.Controllers
{
    [Produces("application/json")]
    [Route("api/[controller]")]
    public class UserTypeController : Controller
    {
        private readonly IAuthTransporter _authTransporter;
        public UserTypeController(IAuthTransporter authTransporter)
        {
            _authTransporter = authTransporter;
        }
        [HttpPost("save"), ServiceFilter(typeof(AuthorizationRequiredAttribute))]
        public IActionResult Save([FromBody] UserType userType)
        {
            return Ok(_authTransporter.UserTypeServices.Save(userType));
        }
    }
}