我有一个现有的 MVC5 应用程序,我正在从使用 AspNetIdentity 转换为使用 ThinkTecture Identity Server 3 v2。OpenID 提供程序不是我遇到的最大问题,因为它似乎运行良好。安全令牌已经过验证,我正在以一种方法处理 SecurityTokenValidated 通知,以便获取额外的用户信息声明并将系统特定的权限声明添加到声明集中,类似于以下代码:
OWIN 中间件
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = "https://localhost:44300/identity",
Caption = "My Application",
ClientId = "implicitclient",
ClientSecret = Convert.ToBase64String(SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes("secret"))),
RedirectUri = "http://localhost:8080/",
ResponseType = "id_token token",
Scope = "openid profile email roles",
SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = ClaimsTransformer.GenerateUserIdentityAsync
}
});
索赔变压器
public static async Task GenerateUserIdentityAsync(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
var identityUser = new ClaimsIdentity(
notification.AuthenticationTicket.Identity.Claims,
notification.AuthenticationTicket.Identity.AuthenticationType,
ClaimTypes.Name,
ClaimTypes.Role);
var userInfoClient = new UserInfoClient(new Uri(notification.Options.Authority + "/connect/userinfo"),
notification.ProtocolMessage.AccessToken);
var userInfo = await userInfoClient.GetAsync();
identityUser.AddClaims(userInfo.Claims.Select(t => new Claim(t.Item1, t.Item2)));
var userName = identityUser.FindFirst("preferred_username").Value;
var user = MembershipProxy.GetUser(userName);
var userId = user.PersonID;
identityUser.AddClaim(new Claim(ClaimTypes.Name, userId.ToString(), ClaimValueTypes.Integer));
// Populate additional claims
notification.AuthenticationTicket = new AuthenticationTicket(identityUser, notification.AuthenticationTicket.Properties);
}
问题是在转换器末端分配给身份验证票证的 ClaimsIdentity 从未填充到 System.Web 管道中。当请求在 OnAuthenticationChallenge 期间到达我的控制器时,我检查 User 属性以找到一个匿名的 WindowsPrincipal,它具有分配给 Identity 属性的类似 WindowsIdentity 实例,就好像 Web 配置的system.web/authentication/@mode
属性设置为 None(至少我相信这是那个模式)。
什么可能导致中间件无法为用户设置主体,或者在 System.Web 处理期间用匿名 Windows 身份替换它?我一直无法追踪到这一点。
编辑:无论是否处理 SecurityTokenValidated 通知并增加声明,都会发生这种情况。
编辑 2:原因似乎是在我的 web.config 中使用 ASP.NET State Service 会话状态服务器和 cookie。配置条目是:
<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" timeout="30" cookieless="UseCookies" />
这看起来与 Microsoft.Owin.Host.SystemWeb #197中报告的问题有关,其中 cookie 没有从 OWIN 请求上下文持久保存到 System.Web 管道中。建议了各种各样的解决方法,但我希望有人权威地向我指出一个经过适当审查的解决方案来解决这个问题。