首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Web API中创建自定义AuthorizeAttribute (.Net框架)

在Web API中创建自定义AuthorizeAttribute (.Net框架)
EN

Stack Overflow用户
提问于 2018-07-28 13:40:35
回答 3查看 23.1K关注 0票数 11

我在WebAPI.My初始令牌响应中使用OAuth2.0owin(密码授予),如下所示

代码语言:javascript
运行
复制
{
    "access_token": "_ramSlQYasdsRTWEWew.....................",
    "token_type": "bearer",
    "expires_in": 17999,
    "permissions": {
        "user": [
            "Add",
            "Update",
            "Delete"
        ],
        "Product": [
            "Read",
            "Create"
        ]
    }
}

我通过创建一个名为permissions的新键来customized响应,这个键拥有相应用户的权限。

从这里开始,我需要验证来自我的Resource server的每个请求,方法是检查用户是否有足够的权限使用Authorize属性调用该接口。

我在here中发现了一个类似的例子,它处理的是Dot net Core,这不适合我的情况。

困难的部分是permission JSON密钥本身与ArrayList之间的复杂性

代码语言:javascript
运行
复制
[CustomAuthorize(PermissionItem.Product, PermissionAction.Read)]
    public async Task<IActionResult> Index()
    {
        return View(Index);
    }

public class CustomAuthorize : AuthorizeAttribute {
    public AuthorizeAttribute (PermissionItem item, PermissionAction action) {
        //Need to initalize the Permission Enums
    }
    public override void OnAuthorization (HttpActionContext actionContext) {
        //Code to get the value from Permissions ArrayList and compare it with the Enum values
    }
}

以上就是我的想法。但是由于Permissions键和枚举比较的复杂性,我无法继续前进。

此外,还有一个问题,比如User的权限是否为Add和Update,这意味着我需要在Controller之前创建两个属性条件。

喜欢

代码语言:javascript
运行
复制
[CustomAuthorize(PermissionItem.User, PermissionAction.Add)]
[CustomAuthorize(PermissionItem.User, PermissionAction.Update)]

这导致添加更多的属性行。那么,有没有办法让它像在一个单独的条件下一样分离|呢?

代码语言:javascript
运行
复制
[CustomAuthorize(PermissionItem.User, PermissionAction.Update|PermissionAction.Add)]
EN

回答 3

Stack Overflow用户

发布于 2018-08-01 13:11:02

为什么不允许您的CustomAuthorize构造函数具有多个权限操作。

代码语言:javascript
运行
复制
public class CustomAuthorize : AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var currentIdentity = System.Threading.Thread.CurrentPrincipal.Identity;
        if (!currentIdentity.IsAuthenticated) {
            // redirect to access denied page
        }

        var userName = currentIdentity.Name;
        // step 1 : retrieve user object

        // step 2 : retrieve user permissions

        // step 3 : match user permission(s) agains class/method's required premissions

        // step 4 : continue/redirect to access denied page
    }
}

您将使用以下命令注释您的类:[CustomAuthorize(PermissionItem.User, PermissionAction.Update, PermissionAction.Add)]

我不确定,OP想要在这里实现什么。如果您依赖于HTTP请求来提供访问权限,那么这是一个很大的安全漏洞。对于每个请求,您应该从数据库中检索用户的访问权限信息,然后根据类/方法的所需权限进行匹配。

根据经验,您不应该依赖request对象来告诉您当前用户拥有哪些权限。您应该从数据存储中检索它们。

My Implementation of CustomAttribute

代码语言:javascript
运行
复制
public class CustomAuthorize : System.Web.Http.AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    protected override Boolean IsAuthorized(HttpActionContext actionContext)
    {
        var currentIdentity = actionContext.RequestContext.Principal.Identity;
        if (!currentIdentity.IsAuthenticated)
            return false;

        var userName = currentIdentity.Name;
        using (var context = new DataContext())
        {
            var userStore = new UserStore<AppUser>(context);
            var userManager = new UserManager<AppUser>(userStore);
            var user = userManager.FindByName(userName);

            if (user == null)
                return false;

            foreach (var role in permissionActions)
                if (!userManager.IsInRole(user.Id, Convert.ToString(role)))
                    return false;

            return true;
        }
    }
}
票数 6
EN

Stack Overflow用户

发布于 2018-08-02 03:45:45

您可以使用标志和二进制操作来允许您|一起执行不同的操作。

下面的代码显示了一个如何完成此操作的小示例

代码语言:javascript
运行
复制
class Program {
    static void Main(string[] args) {
        Test test = new Test();
        CustomAuthorizeAttribute customAuthorizeAttribute = (CustomAuthorizeAttribute)Attribute.GetCustomAttribute(typeof(Test), typeof(CustomAuthorizeAttribute));

        customAuthorizeAttribute.Test();

        Console.ReadKey();
    }
}

[CustomAuthorize(PermissionActions = PermissionAction.Add | PermissionAction.Delete)]
public class Test {

}

public class CustomAuthorizeAttribute : Attribute {
    public PermissionAction PermissionActions { get; set; }

    public void Test() {
        if ((PermissionActions & PermissionAction.Add) == PermissionAction.Add) Console.WriteLine("Add");
        if ((PermissionActions & PermissionAction.Delete) == PermissionAction.Delete) Console.WriteLine("Delete");
        if ((PermissionActions & PermissionAction.Update) == PermissionAction.Update) Console.WriteLine("Update");
    }
}

public enum PermissionAction {
    Add = 1,
    Update = 2,
    Delete = 4
}

这将产生以下输出

票数 1
EN

Stack Overflow用户

发布于 2018-08-07 12:58:55

我们已经创建了下面的API filter来进行身份验证。

这里,"SecretToken","MerchantKey“这两个key传入接口请求。我们正在使用"IsValidMerchant“函数从数据库中验证这两个参数。

IsValidMerchant此函数直接与存储各自值的数据库表连接

代码语言:javascript
运行
复制
public void OnAuthorization(AuthorizationFilterContext actionContext)
{
  const string secretTokenName = "SecretToken";
  const string merchentKeyName = "MerchantKey";
  bool isValid = false;

  if (!actionContext.Filters.Any(item => item is IAllowAnonymousFilter))
    {
     CPServiceResponse response = new CPServiceResponse();
     var secretToken = actionContext.HttpContext.Request.Headers[secretTokenName].FirstOrDefault();
     var merchentKey = actionContext.HttpContext.Request.Headers[merchentKeyName].FirstOrDefault();

      isValid = this.IsValidMerchant(merchentKey, secretToken,_productCode);

       if (isValid == false)
        {
          response.Status = (int)HttpStatusCode.Unauthorized;
          response.Message = Hegic.Shared.Resource.Common.UnauthorizedRequestError;
          actionContext.Result = new JsonResult("")
                {
                    Value = new { Status = response }
                };
         }
      }
  }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51568427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档