OWIN Katana中间件:如果返回的声明在其中没有特定角色,如何阻止用户? [英] OWIN Katana middleware: How to block an user if claims returned doesn't have a specific role in them?

查看:67
本文介绍了OWIN Katana中间件:如果返回的声明在其中没有特定角色,如何阻止用户?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在Identity Server上成功验证了用户的身份,并取回了声明(以及作为角色的角色).当我不考虑角色时,一切都很好.我要限制用户,除非他具有特定角色,然后将他重定向到专门创建的未经授权"或拒绝访问"页面.下面的以下代码不会引发未经授权的异常.

I am successfully authenticating the user at the Identity Server and getting back the claims (along with roles as claims). All is well when I do not consider roles. I want to restrict the user unless he has a specific role and redirect him to a specifically created "Unauthorised" or "Access denied" page. The following code below doesn't raise an unauthorised exception.

var canAccessPortal = id.HasClaim(c => c.Type == "role" && c.Value == "XP");
if (!canAccessPortal)
{
    throw new UnauthorizedAccessException();
}

完整的应用程序.UseOpenIdConnectAuthentication代码如下:

Complete app.UseOpenIdConnectAuthentication code is below:

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

web.config文件中的自定义错误节点:

Custom error node in web.config file:

<customErrors mode="On" defaultRedirect="~/account/error">
  <error statusCode="401" redirect="~/account/unauthorized" />
</customErrors>

推荐答案

在mvc管道中实现授权的最佳位置是实现AuthorizationAttribute.在这里,您可以完全控制请求上下文.如果您要授权MVC,则应实现System.Web.MVC .AuthorizeAttribute并实现重写AuthorizeCore.

The best place to implement authorization in the mvc pipeline is by implementing AuthorizationAttribute. Here you have full control over the request context. Make sure if you are authorizing for MVC you should implement System.Web.MVC .AuthorizeAttribute and implement override 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");
    }

这篇关于OWIN Katana中间件:如果返回的声明在其中没有特定角色,如何阻止用户?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆