Bar*_*osz 4 c# authentication claims-based-identity asp.net-web-api
首先,更广阔的背景。
我正在开发一个由单独的 Web API 支持的 Web 应用程序。Web 应用程序中的身份验证应基于 ActiveDirectory,并且应由 Web API 处理。
因此, Web 应用程序上LogIn
的操作AccountController
仅向AuthenticationController
- 发送一个发布请求,并且我使用 UserPrincipal 和 PrimaryContext 进行 AD 身份验证。身份验证工作正常,我创建了一些声明。
当我需要将结果发回网络应用程序时,问题就开始了,以便我可以像下面这样进行“登录”
if (result.Claims == null)
{
this.Logger.Error($"Something went wrong when discovering identity of user [{model.UserName}]");
throw new InvalidOperationException(Strings_Error.ErrorWhileDiscoveringUserIdentity);
}
IAuthenticationManager authenticationManager = this.HttpContext.GetOwinContext().Authentication;
authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, result.Claims);
Run Code Online (Sandbox Code Playgroud)
我正在使用 JwtSecurityTokenHandler 序列化声明,以便我可以将它们附加到来自 Web Api 控制器的响应消息。序列化发生如下:
public static string GenerateToken(this ClaimsIdentity identity)
{
SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(ClaimsIndentitySerializer.SecurityKey));
SigningCredentials signingCredentials = new SigningCredentials(securityKey,SecurityAlgorithms.HmacSha256Signature);
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
{
Subject = identity,
SigningCredentials = signingCredentials,
Issuer = IssuerKey,
Audience = "http://www.mycompany.com",
};
SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
string tokenString = tokenHandler.WriteToken(token);
return tokenString;
}
Run Code Online (Sandbox Code Playgroud)
然后从字符串生成声明:
public static ClaimsIdentity ReadToken(this string token)
{
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(ClaimsIndentitySerializer.SecurityKey));
TokenValidationParameters validationParameters = new TokenValidationParameters()
{
ValidAudience = "http://www.mycompany.com",
ValidIssuer = IssuerKey,
IssuerSigningKey = securityKey
};
SecurityToken validatedToken = new JwtSecurityToken() as SecurityToken;
ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
return claimsPrincipal.Identity as ClaimsIdentity;
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个单元测试来检查处理后的声明是否匹配。而且,令我惊讶的是,它们有显着的不同。
public void TestClaimsSerialization()
{
ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie, ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);
identity.AddClaim(new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "Active Directory"));
identity.AddClaim(new Claim(ClaimTypes.Name, "TestName"));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "TestNameIdentifier"));
var token = identity.GenerateToken();
var deserialized = token.ReadToken();
Assert.Equal(identity.Name, deserialized.Name);
Assert.Equal(identity.Claims.FirstOrDefault(x=>x.Type == ClaimTypes.NameIdentifier).Value, deserialized.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value);
Assert.Equal(identity.AuthenticationType, deserialized.AuthenticationType); //the last assert fails
}
Run Code Online (Sandbox Code Playgroud)
错误是
Expected: ApplicationCookie Actual: AuthenticationTypes.Federation
其他断言都可以,所以这些值实际上被保留了。
知道为什么吗?
小智 5
AuthenticationType
我通过添加参数解决了同样的问题TokenValidationParameters
。
var validationParameters = new TokenValidationParameters
{
RequireExpirationTime = true,
RequireSignedTokens = true,
ValidateIssuer = true,
ValidIssuer = issuer,
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
ValidateAudience = true,
ValidAudience = audience,
ValidateLifetime = true,
AuthenticationType = "ApplicationCookie"
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7415 次 |
最近记录: |