基于JWT的.Net MVC Core Policy授权 [英] .Net MVC Core Policy based authorization with JWT

查看:141
本文介绍了基于JWT的.Net MVC Core Policy授权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to setup my authorization policy with a jwt based token for my apis. I have two controllers, used by separate apis. I need to make sure a user can only access the ones that he/she is allowed to use. So I figured I'd go with policy based authorization

    [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 ),它详细说明了令牌中的声明的使用.

So my question is, where is the best place to call a stored procedure to check the database for the users application permission. Reading from the following, (https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.1) , it details the use of the claims from the token.

现在,我所保存的JWT令牌具有的是用户ID,名字,姓氏和电子邮件,仅此而已.

Right now what I have with the JWT token that I save is the userid, first name, last name and email, that's it.

推荐答案

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

The best place to check authentication and authorization in ActionFilter, you can check auth policy in database side and also with JWT.

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

If you want to authorise your controller, you have to use a middle ware (ActionFilterAttribute), which will detect user's http request and validate them by decoding user's token. you can filter all http methods (GET,POST,PUT,DELETE...etc), and can implement your own authorisation logic for specific http method.

AuthorizationRequiredAttribute.cs

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

N.B: here all codes are not relevant to your problem. but hope you'll understand how actually i filter get/post request with condition.

[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方法

Now you can use AuthorizationRequiredAttribute as api/controller filter service. i have modified your controller and see the Message method

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!");
        }
    }
}

这篇关于基于JWT的.Net MVC Core Policy授权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆