我有一个用于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();
}
答案 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));
}
}