![](/img/trans.png)
[英]IdentityServer3 - 401 Unauthorized when calling Identity API Controller
[英]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.