带有JWT的基于.Net MVC核心策略的授权

时间:2018-10-16 02:07:07

标签: c# asp.net-mvc asp.net-core-mvc asp.net-authorization

我正在尝试为基于api的基于jwt的令牌设置授权策略。我有两个控制器,分别用于不同的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令牌具有的是用户ID,名字,姓氏和电子邮件,仅此而已。

1 个答案:

答案 0 :(得分:0)

在ActionFilter中检查身份验证和授权的最佳位置,您可以在数据库端以及JWT中检查身份验证策略。

如果要授权控制器,则必须使用中间件( ActionFilterAttribute ),该中间件将检测用户的http请求并通过解码用户的令牌来验证它们。您可以过滤所有http方法(GET,POST,PUT,DELETE等),并可以为特定的http方法实现自己的授权逻辑。

AuthorizationRequiredAttribute.cs

N.B:此处所有代码均与您的问题无关。但希望您能理解我实际上是如何使用条件过滤获取/发布请求的。

[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 /控制器过滤器服务。我已经修改了您的控制器并查看Message方法

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!");
        }
    }
}
相关问题