首页 文章

使用JWT进行基于.Net MVC核心策略的授权

提问于
浏览
0

我正在尝试使用基于jwt的令牌为我的apis设置我的授权策略 . 我有两个控制器,由单独的apis使用 . 我需要确保用户只能访问他/她可以使用的那些用户 . 所以我想我会选择基于策略的授权

[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

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

    如果要授权控制器,则必须使用中间件( ActionFilterAttribute ),它将检测用户's http request and validate them by decoding user'的令牌 . 您可以过滤所有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 / controller过滤服务 . 我修改了你的控制器,看到了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!");
            }
        }
    }
    

相关问题