当前位置: 首页 > 知识库问答 >
问题:

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

殷永嘉
2023-03-14

我试图只允许角色为“Global Administrator”的Azure Active Directory B2C用户访问以下类(这就是为什么我包含了Authorize命令):

[Authorize(Roles = "admin")]
public class UserProfileController : Controller
{
    ... controller class ...
}

我的创业类是这样的:

public partial class Startup
{
    private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
    private static string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
    private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
    private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
    private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
    // This is the resource ID of the AAD Graph API.  We'll need this to request a token to call the Graph API.
    private static string graphResourceId = "https://graph.microsoft.com";
    private static readonly string Authority = aadInstance + tenantId;
    public static GraphServiceClient graphClient = null;

    public static GraphServiceClient GetGraphServiceClient()
    {
        return graphClient;
    }

    public void ConfigureAuth(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions()
        {
            CookieSecure = CookieSecureOption.Always
        });

        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = Authority,
                PostLogoutRedirectUri = postLogoutRedirectUri,

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                   AuthorizationCodeReceived = (context) => 
                   {
                       var code = context.Code;
                       ClientCredential credential = new ClientCredential(clientId, appKey);
                       string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

                       TokenCache userTokenCache = new ADALTokenCache(signedInUserID);

                       AuthenticationContext authContext = new AuthenticationContext(Authority, userTokenCache);
                       AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                           code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);

                       string token = result.AccessToken;

                       try
                       {
                           graphClient = new GraphServiceClient(
                               new DelegateAuthenticationProvider(
                                   (requestMessage) =>
                                   {
                                       requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", token);

                                       return Task.FromResult(0);
                                   }));
                       }
                       catch (Exception e)
                       {
                           System.Diagnostics.Debug.WriteLine("Failed to create graph client: " + e.Message);
                       }

                       return Task.FromResult(0);
                   }
                }
            });
    }
}

共有1个答案

罗绪
2023-03-14

[Authorize(Roles=“admin”)]

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

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

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

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" };
    }
}
[MyAuthorize(Roles = "admin")]
public class UserProfileController : Controller
{
    //TODO:
}

AuthorizationCoderecipeed委托方法下,检索访问令牌后,需要利用Microsoft Graph客户端库检查当前用户是否是全局管理员/公司管理员。如果当前用户是全局管理员/公司管理员,则需要如下指定角色声明:

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

注意:为了检查用户是否是全局管理员,您可以检索当前用户目录下的角色,然后使用getMemberObjects API检索当前用户所属的组、角色,然后检查全局管理员角色id是否在当前用户的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

更新:

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"));
}
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:
}
 类似资料:
  • hasNext()的定义是“如果此扫描仪的输入中有另一个标记,则返回true。此方法可能会在等待输入扫描时阻塞。扫描仪不会前进超过任何输入。” 当我把 standardInput.hasNext() 放在 for 循环中时,程序会向无穷大运行。但是如果我把它放在 while-loop 中,它不会运行到无穷大。这两个程序之间的区别在哪里,为什么其中一个有效而另一个无效? for循环: while-l

  • 我正在用我的java书复习数据结构,我需要重新创建一个循环链表。我对这个无限循环的链表有问题,弄不清楚为什么。我可以将值插入到列表中,但是打印和删除这些值似乎会无限循环最初插入的值。我如何更改我的List类以避免无限循环? CircularList.Class 链接类

  • 基本上,findNode()搜索其数据等于作为参数插入的字符串的节点,但当我调用outputList()方法(该方法返回屏幕上当前节点的字符串表示)时,它将继续无限循环。 outputList方法是: 如有任何帮助,我们将不胜感激。提前道谢。

  • 我正在尝试构建实时聊天消息。在客户端(React),每当有新用户进入聊天时,套接字的事件usuarios-conectados都会被触发(此套接字事件为我提供了当时连接的所有用户的数组)。 然后,我尝试在useState中设置该用户数组,但正因为如此,组件进入循环并不断重新渲染自己。 这似乎是问题所在,因为每当我调用useSocket,控制台时。日志(用户)不断打印连接的用户

  • 我有一个带感应帽的覆盆子皮。我制作了一个二进制时钟,我想在Sense hat的显示器上显示并保持更新。然而,我想要的能力,开关时钟与操纵杆中间。一切都很好,除了我的时钟的更新循环阻止任何新的输入一旦启动。 我一直在考虑如何解决这个问题。如何允许脚本/时钟保持运行,并且仍然接受来自操纵杆的新操作。但是一旦while循环开始,我就卡住了。我不知道该用谷歌搜索什么。我已经开始研究async/await,

  • 问题内容: 为什么我在递归方法中遇到无限循环,而没有机会输入任何符号来破坏它? 如果您尝试创建错误(将字符串值输入键,然后尝试向其添加数字),则您将在控制台中获得无限的“错误”文本,而不是在第一次错误后,程序应再次询问该数字和然后才决定要做什么。 问题答案: 如果失败,则抛出异常,但不使用无效数据。从文档中: 当扫描程序抛出时,扫描程序将不会传递导致异常的令牌,因此可以通过其他方法检索或跳过该令牌