我正在使用Windows身份验证开发Intranet Web App。我使用自定义ClaimsAuthenticationManager使用声明转换。
public class ClaimsTransformer : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return base.Authenticate(resourceName, incomingPrincipal);
}
var newPrinciPal = CreateApplicationPrincipal(incomingPrincipal.Identity.Name);
EstablishSession(newPrinciPal);
return newPrinciPal;
}
private void EstablishSession(ClaimsPrincipal newPrinciPal)
{
var sessionToken = new SessionSecurityToken(newPrinciPal, TimeSpan.FromHours(8))
{
IsPersistent = false,
IsReferenceMode = true
};
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
}
private ClaimsPrincipal CreateApplicationPrincipal(string userName)
{
new SecurityManager().LoginUser(userName);
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, userName));
RPSUser originalIdentity = Thread.CurrentPrincipal.Identity as RPSUser;
if (originalIdentity != null)
{
RPSUserInformation userDetails = originalIdentity.UserDetails;
int splitIndex = userDetails.FullName.IndexOf(' ');
claims.Add(new Claim(ClaimTypes.GivenName, userDetails.FullName.Substring(0, splitIndex)));
claims.Add(new Claim(ClaimTypes.Surname, userDetails.FullName.Substring(splitIndex + 1)));
claims.Add(new Claim(ClaimTypes.Email, userDetails.Email));
claims.Add(new Claim(ClaimTypes.WindowsAccountName, userDetails.LanId));
}
RPSUser transformedIdentity = new RPSUser(new ClaimsIdentity(claims, "Custom"));
transformedIdentity.UserDetails = originalIdentity.UserDetails;
return new RPSPrincipal(transformedIdentity, null);
}
}
在Global.ascx中我有这段代码
protected void Application_PostAuthenticateRequest()
{
try
{
var newPrincipal = FederatedAuthentication.FederationConfiguration
.IdentityConfiguration
.ClaimsAuthenticationManager.Authenticate(string.Empty, ClaimsPrincipal.Current);
SecurityManager.SetIdentityToThread(newPrincipal as RPSPrincipal);
}
catch
{
}
}
此外,我可以从Global.asax中的这段代码中检索/反序列化Cookie
void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender,SessionSecurityTokenReceivedEventArgs e) { var extendSession = true;
if (Request.UrlReferrer.AbsolutePath.Equals("/"))
{
var principal = e.SessionToken.ClaimsPrincipal as RPSPrincipal;
SecurityManager.SetIdentityToThread(principal);
if (extendSession)
{
e.SessionToken = new SessionSecurityToken(
e.SessionToken.ClaimsPrincipal,
TimeSpan.FromHours(8))
{
IsPersistent = false,
IsReferenceMode = true
};
e.ReissueCookie = extendSession;
}
}
}
但问题是即使我能够在此事件中将cookie反序列化为自定义Principal(RPSPrincipal)并且能够将其设置为线程,随后在Application_PostAuthenticateRequest中(对于相同的请求)我们将丢失自定义主体。我们刚刚收到ClaimsPrincipal。
我在这里做错了什么?如果已经设置了自定义主体且Identity的IsAuthenticated属性已设置为true,我如何确保Windows身份验证不会覆盖主体?
或者无论如何在Application_PostAuthenticateRequest事件中访问sessionSecurityToken?