IdentityServer3在身份服务器应用程序

时间:2018-02-28 18:14:43

标签: c# asp.net-mvc asp.net-identity owin identityserver3

我有一个用于SSO的Identity Server 3应用程序。在IdentityServer运行的同一个应用程序中,我集成了Asp.Net MVC控制器以进行用户注册等。但是我有一些方法在没有特定角色的情况下无法访问,我想使用Authorize属性来进行角色检查。

根据这个GitHub线程https://github.com/IdentityServer/IdentityServer3/issues/1148,我设置了控制器使用与IdentityServer相同的基本路由,以便进入Owin管道。

在线程中有一个属性片段,通常可以做我想要的。它对用户进行身份验证并获取他们的一些声明,但问题是许多声明都丢失了 - 例如,角色声明,我需要Authorize属性才能工作。我花了很多时间试图了解为什么缺少索赔,并且真的想避免查询数据库并自己添加它们。

在我的普通客户端应用程序中,我在ClaimsPrincipal中获得的声明是(iss,aud,exp,nbf,nonce,iat,sid,sub,auth_time,idp,preferred_username,email,email_verified,role,website,amr)。正如您将看到sub和amr,其他声明与IdentitySever应用程序在IdentityServerFullLoginAttribute(下面的代码)的帮助下完全不同。

问题是,即使可能,为什么只检索这些声明(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();
    }

1 个答案:

答案 0 :(得分:2)

好的,经过一番努力,我设法把一些东西放在一起完成这项工作。 我正在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));
                }
            }