OWIN Katana中间件:如果返回的声明没有特定的角色,如何阻止用户?
问题描述:
我成功地在身份服务器上对用户进行身份验证,并获取声明(以及声明中的角色)。一切都很好,当我不考虑角色。我想限制用户,除非他具有特定角色并将他重定向到特定创建的“未授权”或“拒绝访问”页面。以下代码不会引发未经授权的异常。OWIN Katana中间件:如果返回的声明没有特定的角色,如何阻止用户?
var canAccessPortal = id.HasClaim(c => c.Type == "role" && c.Value == "XP");
if (!canAccessPortal)
{
throw new UnauthorizedAccessException();
}
完全app.UseOpenIdConnectAuthentication代码如下:在web.config文件
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = ClientId,
Authority = IdServBaseUri,
RedirectUri = ClientUri,
PostLogoutRedirectUri = ClientUri,
ResponseType = "code id_token token",
Scope = "openid profile roles clef",
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
},
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
// use the code to get the access and refresh token
var tokenClient = new TokenClient(
TokenEndpoint,
ClientId,
ClientSecret);
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
// use the access token to retrieve claims from userinfo
var userInfoClient = new UserInfoClient(UserInfoEndpoint);
var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
// create new identity
var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
id.AddClaims(userInfoResponse.Claims);
id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));
var canAccessPortal = id.HasClaim(c => c.Type == "role" && c.Value == "XP");
if (!canAccessPortal)
{
throw new UnauthorizedAccessException();
}
n.AuthenticationTicket = new AuthenticationTicket(
new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
n.AuthenticationTicket.Properties);
},
RedirectToIdentityProvider = n =>
{
// if signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
}
return Task.FromResult(0);
}
}
});
自定义错误节点:
<customErrors mode="On" defaultRedirect="~/account/error">
<error statusCode="401" redirect="~/account/unauthorized" />
</customErrors>
答
实现授权在MVC管道是最好的地方实施AuthorizationAttribute。在这里你可以完全控制请求上下文。确保您是否正在授权MVC,您应该实现System.Web.MVC .AuthorizeAttribute并实现覆盖AuthorizeCore。
protected override bool AuthorizeCore(HttpContextBase httpContext) {
if (!base.AuthorizeCore(httpContext)) {
return false;
}
//Check roles from DB service
return roleservice.UserInRole && UserClaims.Count > 0;
}
/// <summary>
/// Processes HTTP requests that fail authorization.
/// </summary>
/// <param name="filterContext">Encapsulates the information for using <see cref="T:System.Web.Mvc.AuthorizeAttribute" />. The <paramref name="filterContext" /> object contains the controller, HTTP context, request context, action result, and route data.</param>
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
filterContext.Result = new RedirectResult("~/main/unauthorized");
}