ASP.NET 基于身份和声明

ASP.NET Identity and Claim-based

如何使用声明?例如,我想为每个用户设置对每个页面(资源)的访问权限。我知道,我可以使用角色来做到这一点,但据我所知,基于声明的方法更有效。但是当我尝试创建声明时,我看到了以下方法:

        userIdentity.AddClaim(new Claim(ClaimTypes.Role, "test role"));

Claim 的构造函数的第一个参数 class 获取 ClaimTypes 枚举,它有许多 "strange" 成员,如电子邮件,Phone 等。我想设置这个声明然后检查这个声称可以访问某些资源。我走错路了?怎么做?

声明未设置权限。它用于验证您 "you are who you claim to be you are"。这些索赔由发行人(通常是第 3 方)确定。有关说明,请参见例如 this article。 因此,您应该定义哪些声明是必需的(用户应该是谁)才能访问某个页面。否则,使用基于声明的授权将与使用基于身份或基于角色的授权相同。

根据上面的代码,我假设您已经在启动 class 中添加了对您的提供者进行身份验证的声明,如下所示。

context.Identity.AddClaim(new Claim("urn:google:name", context.Identity.FindFirstValue(ClaimTypes.Name))); // added claim for reading google name
context.Identity.AddClaim(new Claim("urn:google:email", context.Identity.FindFirstValue(ClaimTypes.Email))); // and email too

在启动时添加声明后,在实际处理请求时检查它是否是回调,如果是,请阅读以下声明(在 IHttpHandler 中)。

public void ProcessRequest(HttpContext context)
    {
        IAuthenticationManager authManager = context.GetOwinContext().Authentication;
        if (string.IsNullOrEmpty(context.Request.QueryString[CallBackKey]))
        {
            string providerName = context.Request.QueryString["provider"] ?? "Google";//I have multiple providers so checking if its google
            RedirectToProvider(context, authManager, providerName);
        }
        else
        {
            ExternalLoginCallback(context, authManager);
        }
    }

如果它的第一次调用重定向到提供商

private static void RedirectToProvider(HttpContext context, IAuthenticationManager authManager, string providerName)
    {
        var loginProviders = authManager.GetExternalAuthenticationTypes();

        var LoginProvider = loginProviders.Single(x => x.Caption == providerName);

        var properties = new AuthenticationProperties()
        {
            RedirectUri = String.Format("{0}&{1}=true", context.Request.Url, CallBackKey)
        };

        //string[] authTypes = { LoginProvider.AuthenticationType, DefaultAuthenticationTypes.ExternalCookie };
        authManager.Challenge(properties, LoginProvider.AuthenticationType);

        //without this it redirect to forms login page
        context.Response.SuppressFormsAuthenticationRedirect = true;
    }

最后阅读您收到的索赔

public void ExternalLoginCallback(HttpContext context, IAuthenticationManager authManager)
    {
        var loginInfo = authManager.GetExternalLoginInfo();
        if (loginInfo == null)
        {
            throw new System.Security.SecurityException("Failed to login");
        }

        var LoginProvider = loginInfo.Login.LoginProvider;
        var ExternalLoginConfirmation = loginInfo.DefaultUserName;

        var externalIdentity = authManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
        var emailClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email);
        var email = emailClaim.Value;

        var pictureClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type.Equals("picture"));
        var pictureUrl = pictureClaim.Value;

        LogInByEmail(context, email, LoginProvider); //redirects to my method of adding claimed user as logged in, you will use yours.
    }