JWT Token от почтальона никогда не попадает в контроллер с атрибутом Authorize - PullRequest
0 голосов
/ 29 января 2019

Попытка понять, как работает 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 голосов
/ 29 января 2019

Мое ниже решение немного отличается, но это решение поможет вам справиться с пользовательской реализацией аутентификации, вы можете реализовать другой тип аутентификации для разных типов пользователей.Вам необходимо создать класс AuthorizationRequiredAttribute в вашем проекте API, этот класс будет наследовать класс 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));
        }
    }
}
...