且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

[[Authorize(Roles ="admin"))]`无限循环ASP.NET MVC和Azure Active Directory B2C

更新时间:2023-02-21 10:06:53

[Authorize(Roles ="admin")]

[Authorize(Roles = "admin")]

由于您使用的是Authorize属性来检查用户的角色,因此需要确保当前用户的Claims具有有效的角色声明.您可以利用以下代码片段检查当前的用户声明:

Since your are using the Authorize attribute to check user's roles, you need to make sure the current user's Claims have the valid role claim. You could leverage the following code snippet to check your current user claims:

return Json((User.Identity as ClaimsIdentity).Claims.Select(c => new { key = c.Type, value = c.Value }),JsonRequestBehavior.AllowGet);

问题是:当我单击实例化UserProfileController的按钮时,然后在无限循环中一次又一次地调用AuthorizationCodeReceived =(context)=>代码行中的代码.

The problem is: when I click on the button that instantiates the UserProfileController, then the the code inside of AuthorizationCodeReceived = (context) => line of code is called again and again in an infinite loop.

您可以在HandleUnauthorizedRequest方法" rel ="nofollow noreferrer"> AuthorizeAttribute 并按如下所示定义您的自定义授权属性:

You could override the HandleUnauthorizedRequest method under AuthorizeAttribute and define your custom authorize attribute as follows:

public class MyAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        filterContext.Result = new ContentResult() { Content = "You don't have rights to take actions" };
    }
}

然后,您可以按以下方式装饰UserProfileController控制器:

Then, you could decorate your UserProfileController controller as follows:

[MyAuthorize(Roles = "admin")]
public class UserProfileController : Controller
{
    //TODO:
}

我试图仅允许角色为全局管理员"的Azure Active Directory B2C用户访问以下类

I am attempting to allow only Azure Active Directory B2C users with role "Global Administrator" to access the following class

AuthorizationCodeReceived委托方法下,检索访问令牌后,需要利用Microsoft Graph Client库检查当前用户是否为 Global Administrator/Company Administrator .如果当前用户是全局管理员/公司管理员,则需要指定角色声明,如下所示:

Under the AuthorizationCodeReceived delegate method, after you retrieve the access token, you need to leverage the Microsoft Graph Client library to check whether the current user is a Global Administrator / Company Administrator or not. If the current user is a Global Administrator / Company Administrator, then you need to specify the role claim as follows:

context.AuthenticationTicket.Identity.AddClaim(new Claim(context.AuthenticationTicket.Identity.RoleClaimType, "admin"));

注意::要检查用户是否是全局管理员,可以检索当前用户目录下的角色,然后使用

Note: For checking whether a user is a Global Administrator, you could retrieve the roles under the current user's directory, then use the getMemberObjects API to retrieve the groups, roles that the current user is a member of, then check whether the Global Administrator role id is in current user's MemberObjects.

//List directory roles, https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/directoryrole_list
var roles=await graphClient.DirectoryRoles.Request().GetAsync();

//user: getMemberObjects ,https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/user_getmemberobjects

更新:

我检查了我这一边的实施情况.这是检查当前登录用户角色的代码.

I checked the implementation on my side. Here is the code to check the role for the current logged user.

var directoryRoles = await graphClient.DirectoryRoles.Request().GetAsync();
var userRoles = await graphClient.Me.MemberOf.Request().GetAsync();

var adminRole=directoryRoles.Where(role => role.DisplayName== "Company Administrator" || role.DisplayName == "Global Administrator").FirstOrDefault();
if (userRoles.Count(role => role.Id == adminRole.Id) > 0)
{
    context.AuthenticationTicket.Identity.AddClaim(new Claim(context.AuthenticationTicket.Identity.RoleClaimType, "admin"));
}
else
{
    context.AuthenticationTicket.Identity.AddClaim(new Claim(context.AuthenticationTicket.Identity.RoleClaimType, "user"));
}

注意:要添加多个用户角色,可以添加多个new Claim(context.AuthenticationTicket.Identity.RoleClaimType, "<role-name>")角色声明.

Note: For adding multiple user roles, you could add multiple new Claim(context.AuthenticationTicket.Identity.RoleClaimType, "<role-name>") role claims.

这是我修改后的自定义AuthorizeAttribute:

Here is my modified custom AuthorizeAttribute:

public class MyAuthorize : AuthorizeAttribute
{
    private bool noPermission = false;

    public string Permissions { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (!base.AuthorizeCore(httpContext))
            return false;

        var permissionArrs = Permissions.Trim().Split('|');

        if (permissionArrs.ToList().Exists(p=>httpContext.User.IsInRole(p)))
        {
            return true;
        }
        else
        {
            noPermission = true;
            return false;
        }
    }

    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (noPermission)
            filterContext.Result = new ContentResult() { Content = "You don't have rights to take actions" };
        else
            base.HandleUnauthorizedRequest(filterContext);
    }
}

装饰UserProfileController如下:

[MyAuthorize(Permissions = "admin|co-admin")]
public class UsersController : Controller
{
   //TODO:
}