.Net MVC Базовая политика на основе авторизации с JWT - PullRequest
0 голосов
/ 16 октября 2018

Я пытаюсь настроить мою политику авторизации с помощью токена на основе jwt для моего apis.У меня есть два контроллера, используемые отдельным API.Мне нужно убедиться, что пользователь может получить доступ только к тем, которые ему разрешено использовать.Поэтому я решил пойти с авторизацией на основе политик

    [Authorize(Policy = "API1")]
    [Route("api1/endpoint")]
    public class API1Controller : Controller
    {
           // my actions for api 1
     }
    [Authorize(Policy = "API2")]
    [Route("api2/endpoint")]
    public class API2Controller : Controller
    {
           // my actions for api 2
    }

Добавление политик при запуске

    services.AddAuthorization(options => {
                    options.AddPolicy("API1User", policy => policy.Requirements.Add(new ApplicationTypeRequirement(ApplicationType.API1)));
                    options.AddPolicy("API2User", policy => policy.Requirements.Add(new ApplicationTypeRequirement(ApplicationType.API2)));
                });
//  Adding handlers after this

Поэтому мой вопрос: где лучше всего вызвать хранимую процедуру для проверки?база данных для разрешения приложения пользователя.Читая из следующего (https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.1), он детализирует использование утверждений из токена.

Прямо сейчас, что я сохраняю с токеном JWT, это идентификатор пользователя, имя, фамилияимя и адрес электронной почты, вот и все.

1 Ответ

0 голосов
/ 16 октября 2018

Лучшее место для проверки аутентификации и авторизации в ActionFilter, вы можете проверить политику аутентификации на стороне базы данных, а также с помощью JWT.

Если вы хотите авторизовать свой контроллер, вы должны использовать промежуточное программное обеспечение ( ActionFilterAttribute ), которое будет обнаруживать http-запрос пользователя и проверять его путем декодирования токена пользователя.Вы можете отфильтровать все методы http (GET, POST, PUT, DELETE ... и т. д.) и реализовать собственную логику авторизации для конкретного метода http.

AuthorizationRequiredAttribute.cs

Примечание: здесь все коды не имеют отношения к вашей проблеме.но надеюсь, вы поймете, как на самом деле я фильтрую запрос на получение / публикацию с условием.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class AuthorizationRequiredAttribute : ActionFilterAttribute
{
    private readonly IAccessTokenServices _accessTokenServices;
    private readonly IPermissionServices _permissionServices;
    private readonly IAuditLogServices _auditLogServices;
    private IConfiguration _config;
    public AuthorizationRequiredAttribute(IAccessTokenServices accessTokenServices, IPermissionServices permissionServices,
        IAuditLogServices auditLogServices,IConfiguration config)
    {
        _accessTokenServices = accessTokenServices;
        _config = config;
        _permissionServices = permissionServices;
        _auditLogServices = auditLogServices;
    }
    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
                {

                    var accessToken = _accessTokenServices
                        .Details(x => x.Token == context.HttpContext.Request.Headers[Constants.HttpHeaders.Token]);
                    if (accessToken != null)
                    {
                        if (accessToken.ExpiresOn < DateTime.Now)
                        {
                            _accessTokenServices.Delete(accessToken);
                            context.Result = new UnauthorizedResult();
                        }
                        else
                        {
                            var userId = Convert.ToInt32(token.Claims.First(claim => claim.Type == Constants.JwtClaims.UserId).Value);
                            var userTypeId = Convert.ToInt32(token.Claims.First(claim => claim.Type == Constants.JwtClaims.UserTypeId).Value);
                            if (accessToken == null)
                            {
                                context.Result = new UnauthorizedResult();
                            }
                            else if (!_permissionServices.IsPermissionExist(context.HttpContext.Request.Path.ToString(), userTypeId))
                            {
                                context.Result = new StatusCodeResult((int)HttpStatusCode.NotAcceptable);
                            }
                            else
                            {

                                _auditLogServices.Save(context.HttpContext.Request.Path.ToString(), userId);
                                accessToken.ExpiresOn = DateTime.Now.AddMinutes(Convert.ToInt16(_config["Jwt:ExpiresOn"]));
                                _accessTokenServices.UpdateExpireTime(accessToken);

                            }
                        }
                    }
                    else
                    {
                        context.Result = new UnauthorizedResult();
                    }
                }
            }
            else
            {
                context.Result = new NotFoundResult();
            }
        }
        catch (Exception ex)
        {
            context.Result = new BadRequestResult();
        }
        base.OnActionExecuting(context);
    }
}

}

HomeController.cs

Теперь вы можете использовать AuthorizationRequiredAttribute в качестве службы фильтрации API / контроллера.я изменил ваш контроллер и вижу метод сообщения

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace Chat.Controllers
{
    [Route("api/home")]
    public class HomeController : Controller
    {

        public IActionResult Index()
        {
            return View();
        }

        [HttpGet("message"), ServiceFilter(typeof(AuthorizationRequiredAttribute))]
        public IActionResult Message()
        {
            return Ok("Hello World!");
        }
    }
}
...