简体   繁体   English

IdentityServer3 在身份服务器应用程序中的自定义 MVC 控制器中授权

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

I have an Identity Server 3 application used for SSO.我有一个用于 SSO 的 Identity Server 3 应用程序。 In the same application in which the IdentityServer is running I have integrated Asp.Net MVC controllers for user registration and so on.在运行 IdentityServer 的同一个应用程序中,我集成了用于用户注册等的 Asp.Net MVC 控制器。 However I have some methods which cannot be accessed without a specific role and I want to use the Authorize attribute in order to do the role check.但是,我有一些方法在没有特定角色的情况下无法访问,我想使用 Authorize 属性来进行角色检查。

As per this GitHub thread https://github.com/IdentityServer/IdentityServer3/issues/1148 I have setup said controller to use the same base route as IdentityServer in order to be in the Owin pipeline.根据此 GitHub 线程https://github.com/IdentityServer/IdentityServer3/issues/1148,我已将所述控制器设置为使用与 IdentityServer 相同的基本路由,以便进入 Owin 管道。

In the thread there is an attribute snippet which in general does what I want.在线程中有一个属性片段,它通常可以满足我的要求。 It authenticates the user and gets some of their claims, but the problem is that many claims are missing- the role claim, for example, which I need for the Authorize attribute to work.它对用户进行身份验证并获取他们的一些声明,但问题是缺少许多声明 - 例如,我需要授权属性才能工作的角色声明。 I spent many hours trying to see why there are missing claims and really want to avoid querying the database and adding them myself.我花了很多时间试图了解为什么缺少声明,并且真的想避免查询数据库并自己添加它们。

In my normal client applications the claims I get in the ClaimsPrincipal are (iss,aud,exp,nbf,nonce,iat,sid,sub,auth_time,idp,preferred_username,email,email_verified,role,website,amr).在我的普通客户端应用程序中,我在 ClaimsPrincipal 中得到的声明是(iss、aud、exp、nbf、nonce、iat、sid、sub、auth_time、idp、preferred_username、email、email_verified、role、website、amr)。 As you will see apart from sub and amr, the other claims are completely different from what I get in the IdentitySever application with the help of IdentityServerFullLoginAttribute (code below).正如您将看到的,除了 sub 和 amr 之外,其他声明与我在 IdentityServerFullLoginAttribute(下面的代码)的帮助下在 IdentitySever 应用程序中获得的声明完全不同。

The question is is that even possible and why are just these claims retrieved(sub, name, amr, idp, auth_time, security_stamp)?问题是这甚至是可能的,为什么只检索这些声明(sub、name、amr、idp、auth_time、security_stamp)?

This is my IdentityServer config:这是我的 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'"
                }
            });
        });

And this is the said attribute I am using to allow the user to be authenticated这是我用来允许用户进行身份验证的上述属性

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);
        }
    }
}

And this is the controller action:这是控制器操作:

    [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();
    }

Ok, so after a bit of a struggle I managed to put something together that does the job.好的,所以经过一番挣扎后,我设法将一些东西放在一起来完成这项工作。 I am retrieving the needed claims in OnAuthentication() in OwinAuthenticationAttribute like this:我正在 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.

相关问题 IdentityServer3-401调用Identity API Controller时未授权 - IdentityServer3 - 401 Unauthorized when calling Identity API Controller Identityserver3 可以作为具有 SAML(C#、MVC)的身份提供者吗? - Can Identityserver3 act as a Identity Provider with SAML (C#, MVC)? IdentityServer3如何使用signin =从MVC客户端应用程序重定向用户 - IdentityServer3 How to redirect user from MVC Client application with signin= 具有附加MVC控制器的IdentityServer3自定义OWIN中间件 - IdentityServer3 Custom OWIN Middleware with additional MVC controllers IdentityServer3-如何在PreAuthenticateAsync中获得部分身份? - IdentityServer3 - how to get partial identity in PreAuthenticateAsync? 如何为IdentityServer3设置MVC客户端 - How to setup an MVC client for IdentityServer3 Authorize标记上的角色和IdentityServer3客户端设置之间是什么关系? - What is the relationship between Roles on the Authorize tag and IdentityServer3 client setup 401未经ASP.Net Core 1.1 MVC应用程序中IdentityServer3的授权 - 401 Unauthorized with IdentityServer3 In ASP.Net Core 1.1 MVC Application IdentityServer3 将注销重定向到自定义 URL - IdentityServer3 redirect Logout to the Custom URL ASP.Net MVC IdentityServer3破坏了我的webapi路由 - ASP.Net MVC IdentityServer3 broke my webapi routing
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM