Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# `[Authorize(Roles=";admin";)]`无限循环ASP.NET MVC和Azure Active Directory B2C_C#_Asp.net Mvc_Azure_Oauth 2.0 - Fatal编程技术网

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

C# `[Authorize(Roles=";admin";)]`无限循环ASP.NET MVC和Azure Active Directory B2C,c#,asp.net-mvc,azure,oauth-2.0,C#,Asp.net Mvc,Azure,Oauth 2.0,我正在尝试仅允许具有“全局管理员”角色的Azure Active Directory B2C用户访问以下类(这就是为什么我包含了Authorize命令): 我的Startup类如下所示: public partial class Startup { private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; private static string appKey = Con

我正在尝试仅允许具有“全局管理员”角色的Azure Active Directory B2C用户访问以下类(这就是为什么我包含了
Authorize
命令):

我的Startup类如下所示:

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);
                   }
                }
            });
    }
}
问题是:当我单击实例化UserProfileController的按钮时,
AuthorizationCodeReceived=(context)=>
代码行中的代码在无限循环中被一次又一次地调用。
我如何修复无限循环,以便只有Azure Active Directory B2C“全局管理员”才能执行此操作可以实例化UserProfileController吗

[授权(Roles=“admin”)]

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

return Json((User.Identity as ClaimsIdentity).Claims.Select(c => new { key = c.Type, value = c.Value }),JsonRequestBehavior.AllowGet);
问题是:当我单击实例化UserProfileController的按钮时,AuthorizationCodeReceived=(context)=>代码行中的代码在无限循环中被一次又一次地调用

您可以覆盖下的
HandleUnauthorizedRequest
方法,并定义自定义授权属性,如下所示:

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" };
    }
}
context.AuthenticationTicket.Identity.AddClaim(new Claim(context.AuthenticationTicket.Identity.RoleClaimType, "admin"));
[MyAuthorize(Permissions = "admin|co-admin")]
public class UsersController : Controller
{
   //TODO:
}
然后,您可以按照如下方式装饰
UserProfileController
控制器:

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" };
    }
}
context.AuthenticationTicket.Identity.AddClaim(new Claim(context.AuthenticationTicket.Identity.RoleClaimType, "admin"));
[MyAuthorize(Permissions = "admin|co-admin")]
public class UsersController : Controller
{
   //TODO:
}
[MyAuthorize(Roles=“admin”)]
公共类UserProfileController:控制器
{
//待办事项:
}
我正在尝试仅允许角色为“全局管理员”的Azure Active Directory B2C用户访问以下类

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

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" };
    }
}
context.AuthenticationTicket.Identity.AddClaim(new Claim(context.AuthenticationTicket.Identity.RoleClaimType, "admin"));
[MyAuthorize(Permissions = "admin|co-admin")]
public class UsersController : Controller
{
   //TODO:
}
注意:要检查用户是否为全局管理员,可以检索当前用户目录下的角色,然后使用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"));
}
注意:要添加多个用户角色,可以添加多个
新声明(context.AuthenticationTicket.Identity.RoleClaimType,”)
角色声明

这是我修改的自定义
授权属性

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

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" };
    }
}
context.AuthenticationTicket.Identity.AddClaim(new Claim(context.AuthenticationTicket.Identity.RoleClaimType, "admin"));
[MyAuthorize(Permissions = "admin|co-admin")]
public class UsersController : Controller
{
   //TODO:
}

非常感谢你的帮助!我无法获取
返回Json((User.Identity as ClaimsIdentity).Claims.Select(c=>new{key=c.Type,value=c.value}),JsonRequestBehavior.AllowGet)代码段正在工作,因为“用户”没有属性“标识”。但是,我能够实现以下功能:
ClaimsPrincipal principal=HttpContext.Current.User as ClaimsPrincipal;foreach(System.Security.Claims.Claim-Claim-in-principal.Claims){var-type=Claim.type;var-value=Claim.value;}
然而,问题是
Claim
总是
空的。你知道这是为什么吗?再次感谢你,这是我的遗产。另外,我已经检查了您的代码
HttpContext.Current.User as ClaimsPrincipal
,在我的MVC控制器下,它可以按预期工作。请尝试调用
ClaimsPrincipal.Current.Claims
以在您的操作中获取索赔。此外,您是否在您的
AuthorizationCodeReceived
委托方法中检查了
context.AuthenticationTicket.Identity.Claims
?我想我就快到了。正如您最初的回答所建议的,我列出了目录角色,其中包含
var directoryRoles=await-graphClient.directoryRoles.Request().GetAsync(),循环遍历这些角色,并找到“公司管理员”角色的id。然后,我将结果与
var userRoles=wait graphClient.Me.MemberOf.Request().GetAsync()的结果进行比较。如果“公司管理员”角色的Id在userRoles中,那么我添加了如下声明:
context.AuthenticationTicket.Identity.AddClaim(新声明(context.AuthenticationTicket.Identity.RoleClaimType,“Admin”)。我还添加了
MyAuthorize
class(继续上面的注释)。当当前登录的用户是“公司管理员”时,此操作有效!然而,当当前登录的用户只是一个“来宾”时,我看到了无限循环问题。是否缺少重定向到
MyAuthorize
类以显示错误消息的额外步骤?我测试了我这边的代码,您可以按照我答案中更新的部分进行操作。