簡體   English   中英

IdentityServer3 在身份服務器應用程序中的自定義 MVC 控制器中授權

[英]IdentityServer3 Authorize in custom MVC controller in identity server application

我有一個用於 SSO 的 Identity Server 3 應用程序。 在運行 IdentityServer 的同一個應用程序中,我集成了用於用戶注冊等的 Asp.Net MVC 控制器。 但是,我有一些方法在沒有特定角色的情況下無法訪問,我想使用 Authorize 屬性來進行角色檢查。

根據此 GitHub 線程https://github.com/IdentityServer/IdentityServer3/issues/1148,我已將所述控制器設置為使用與 IdentityServer 相同的基本路由,以便進入 Owin 管道。

在線程中有一個屬性片段,它通常可以滿足我的要求。 它對用戶進行身份驗證並獲取他們的一些聲明,但問題是缺少許多聲明 - 例如,我需要授權屬性才能工作的角色聲明。 我花了很多時間試圖了解為什么缺少聲明,並且真的想避免查詢數據庫並自己添加它們。

在我的普通客戶端應用程序中,我在 ClaimsPrincipal 中得到的聲明是(iss、aud、exp、nbf、nonce、iat、sid、sub、auth_time、idp、preferred_username、email、email_verified、role、website、amr)。 正如您將看到的,除了 sub 和 amr 之外,其他聲明與我在 IdentityServerFullLoginAttribute(下面的代碼)的幫助下在 IdentitySever 應用程序中獲得的聲明完全不同。

問題是這甚至是可能的,為什么只檢索這些聲明(sub、name、amr、idp、auth_time、security_stamp)?

這是我的 IdentityServer 配置:

coreApp.UseIdentityServer(new IdentityServerOptions
            {
                Factory = factory,
                SigningCertificate = signingCertificate,
                SiteName = "Sitename",
                RequireSsl = true,
                LoggingOptions = new LoggingOptions
                {
                    EnableKatanaLogging = true
                },
                EventsOptions = new EventsOptions
                {
                    RaiseFailureEvents = true,
                    RaiseInformationEvents = true,
                    RaiseSuccessEvents = true,
                    RaiseErrorEvents = true
                },
                CspOptions = new CspOptions
                {
                    Enabled = true,
                    ScriptSrc = "'unsafe-eval' 'unsafe-inline'"
                }
            });
        });

這是我用來允許用戶進行身份驗證的上述屬性

public abstract class OwinAuthenticationAttribute : FilterAttribute, IAuthenticationFilter
{
    public string AuthenticationType { get; set; }

    protected OwinAuthenticationAttribute(string authenticationType)
    {
        if (String.IsNullOrWhiteSpace(authenticationType)) throw new ArgumentNullException("authenticationType");

        AuthenticationType = authenticationType;
    }

    public virtual void OnAuthentication(AuthenticationContext filterContext)
    {
        var ctx = filterContext.HttpContext.Request.GetOwinContext();
        var result = AsyncHelper.RunSync(() => ctx.Authentication.AuthenticateAsync(AuthenticationType));
        if (result != null &&
            result.Identity != null &&
            result.Identity.IsAuthenticated)
        {
            filterContext.Principal = new ClaimsPrincipal(result.Identity);
        }
    }

    public abstract void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);
}

public class IdentityServerFullLoginAttribute : OwinAuthenticationAttribute
{
    public IdentityServerFullLoginAttribute()
        : base(Constants.PrimaryAuthenticationType)
    {
        this.Order = 1;
    }

    public override void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
        var statusCodeResult = filterContext.Result as HttpStatusCodeResult;
        if (statusCodeResult != null && statusCodeResult.StatusCode == 401)
        {
            var ctx = filterContext.HttpContext.Request.GetOwinContext();
            var url = ctx.Environment.CreateSignInRequest(new SignInMessage
            {
                ReturnUrl = filterContext.HttpContext.Request.Url.AbsoluteUri
            });
            filterContext.Result = new RedirectResult(url);
        }
    }
}

這是控制器操作:

    [HttpGet]
    [Route("core/test/test")]
    [IdentityServerFullLogin]
    [Authorize(Roles = "Administrator")]
    public EmptyResult Test(string signin)
    {
        //return Redirect("~/core/" + IdentityServer3.Core.Constants.RoutePaths.Login + "?signin=" + signin);

        return new EmptyResult();
    }

好的,所以經過一番掙扎后,我設法將一些東西放在一起來完成這項工作。 我正在 OwinAuthenticationAttribute 中的 OnAuthentication() 中檢索所需的聲明,如下所示:

            var userManager = ctx.GetUserManager<ApplicationUserManager>();
            string sub = result.Identity.FindFirst("sub")?.Value;

            if (userManager.SupportsUserClaim)
            {
                result.Identity.AddClaims(await userManager.GetClaimsAsync(sub));
            }

            if (userManager.SupportsUserRole)
            {
                IList<string> roles = await userManager.GetRolesAsync(sub);

                foreach (string roleName in roles)
                {
                    result.Identity.AddClaim(new Claim(IdentityServer3.Core.Constants.ClaimTypes.Role, roleName, ClaimValueTypes.String));
                }
            }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM