[英]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.