在请求中保留新的声明

问题描述 投票:2回答:3

如何以这样的方式添加新声明,以便它们在Cookie到期之前一直存在请求?

我正在使用OWIN中间件,本地身份验证来验证登录系统的用户。

登录部分是成功的,我将角色添加到ws-federation提供的用户声明中,以帮助授权用户使用某些操作方法。在登录时,在控制器中,我编写了以下内容来添加角色:

string[] roles = { "Role1", "Role2" };

var identity = new ClaimsIdentity(User.Identity);
foreach (var role in roles)
{
    identity.AddClaim(new Claim(ClaimTypes.Role, role));
}

var authenticationManager = HttpContext.GetOwinContext().Authentication;

authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant
                             (new ClaimsPrincipal(identity),
                              new AuthenticationProperties { IsPersistent = true });

但是当我在下一个请求中检查声明时,我没有看到角色声明。

c# .net owin claims-based-identity ws-federation
3个回答
1
投票

在成功验证后,我相信您添加了自定义声明(通常在成功验证后对某些事件处理程序)。现在,为了在后续请求中保留该信息,您需要在管道中进行身份验证之前使用CookieAuthentication中间件。

这个怎么运作 :

在第一次成功验证并添加自定义声明后,声明将转换为一种身份验证cookie并发送回客户端。后续请求将携带此身份验证cookie。查找auth cookie的CookieAuthentication中间件会将Thread.CurrentPriciple设置为从cookie获取的声明。

在cookie中间件确实看到任何auth cookie的第一次请求期间,它将请求传递到管道中的下一个中间件(在您的情况下为身份验证)以挑战用户登录。

app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

app.UseCookieAuthentication(new CookieAuthenticationOptions()
            {

                AuthenticationType = "Cookies",
                AuthenticationMode= AuthenticationMode.Active,
                CookieName="XXXXX",
                CookieDomain= _cookiedomain,
                /* you can go with default cookie encryption also */
                TicketDataFormat = new TicketDataFormat(_x509DataProtector),
                SlidingExpiration = true,
                CookieSecure = CookieSecureOption.Always,
            });


app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {

                ClientId = _clientID,
                Authority = _authority,
                RedirectUri = _redirectUri,
                UseTokenLifetime = false,

                Notifications = new OpenIdConnectAuthenticationNotifications
                {

                    SecurityTokenValidated = SecurityTokenValidated,

                    AuthenticationFailed = (context) =>
                    {
                        /* your logic to handle failure*/
                    }
                },

                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidIssuers = _validIssuers,
                    ValidateIssuer = _isValidIssuers,
                }
            });

编辑:(附加信息) 几乎上面的确切代码也适用于ws联邦,具有相同的逻辑和一切。

SecurityTokenValidated = notification =>
{
    ClaimsIdentity identity = notification.AuthenticationTicket.Identity;
    string[] roles = { "Role1", "Role2" };
    foreach (var role in roles)
    {
        identity.AddClaim(new Claim(ClaimTypes.Role, role));
    }
    return Task.FromResult(0);
}

0
投票

您需要使用AuthenticationType中使用的相同Startup.ConfigureAuth。例如:

Startup.ConfigureAuth

app.UseCookieAuthentication(new CookieAuthenticationOptions {
  AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
  //....
});

并在您的登录代码中(在问题中提供):

var identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie);

或者确保User.Identity具有相同的AuthenticationType,并且您可以像使用它一样使用它:

var identity = new ClaimsIdentity(User.Identity);

现在重要的一点是,对于登录,你应该在唱歌使用之前添加声明,而不是之后。像这样的东西:

HttpContext.GetOwinContext().Authentication.SignIn(identity);

您可以在登录后添加声明,但是您将在创建cookie后立即对其进行修改,这效率不高。如果在某些其他代码中您需要修改声明,那么您可以使用与您的代码类似的内容,但您必须从Current获取上下文:

HttpContext.Current.GetOwinContext().Authentication.AuthenticationResponseGrant =
    new AuthenticationResponseGrant(new ClaimsPrincipal(identity),
                                    new AuthenticationProperties { IsPersistent = true });

因此,您可以通过简单地添加上面的Current来修复代码,但这对登录代码效率不高,最好将声明传递给SignIn函数。


0
投票

您可以在WEB API C#(SOAP)中执行以下操作,(存储过程)

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
        LoginModel model = new LoginModel();
        //validate user credentials and obtain user roles (return List Roles) 
        //validar las credenciales de usuario y obtener roles de usuario
        var user = model.User = _serviceUsuario.ObtenerUsuario(context.UserName, context.Password);
        if (user == null)
        {
            context.SetError("invalid_grant", "El nombre de usuario o la contraseña no son correctos.cod 01");
            return;
        }

        var stringRoles = user.Roles.Replace(" ", "");//It depends on how you bring them from your DB
        string[] roles = stringRoles.Split(',');//It depends on how you bring them from your DB

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);          
        foreach(var Rol in roles)
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, Rol));
        }
        identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
        identity.AddClaim(new Claim(ClaimTypes.Email, user.Correo));
        identity.AddClaim(new Claim(ClaimTypes.MobilePhone, user.Celular));
        identity.AddClaim(new Claim("FullName", user.FullName));//new ClaimTypes
        identity.AddClaim(new Claim("Empresa", user.Empresa));//new ClaimTypes
        identity.AddClaim(new Claim("ConnectionStringsName", user.ConnectionStringsName));//new ClaimTypes
//add user information for the client
        var properties = new AuthenticationProperties(new Dictionary<string, string>
        {
            { "userName",user.NombreUsuario },
            { "FullName",user.FullName },
            { "EmpresaName",user.Empresa }
        });
//end
        var ticket = new AuthenticationTicket(identity, properties);
       context.Validated(ticket);
    }
© www.soinside.com 2019 - 2024. All rights reserved.