c# - .Net Claims Auth——无法设置当前主体

标签 c# asp.net asp.net-mvc-4 authentication claims-based-identity

我正在尝试使用基于声明的身份验证重新创建登录系统。

到目前为止,还不错

逐步执行,它似乎正确地评估了用户名和密码并正确地创建了声明主体(包括添加身份验证类型以将 IsAuthenticated 设置为 true,per this SO question。)

但是……

不知何故,身份似乎无法正确地在线上设置。结果,我被直接重定向回登录页面。

代码

我在 global.asax 中有以下内容:

private void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
    var currentPrincipal = ClaimsPrincipal.Current; 
    var transformer = new ClaimsTransformer(); //My own custom transformer; code below.
    var newPrincipal = transformer.Authenticate(string.Empty, currentPrincipal); // does the transformation

    // as I understand, it is proper & recommnded to set both of these
    Thread.CurrentPrincipal = newPrincipal;
    HttpContext.Current.User = newPrincipal;
}

在我的登录 Controller 中,我对成员(member)数据库进行了简单测试。我在调试时验证了这具有 newCP 作为具有预期名称的有效、经过身份验证的身份。

[HttpPost]
[AllowAnonymous]
public ActionResult UserLogin(LoginViewModel viewModel)
{

    var loginSuccess = Membership.ValidateUser(viewModel.UserName, viewModel.Password);

    if (loginSuccess)
    {
        // CustomApplicationIdentity puts some identity-based logic into business domain terms and uses Claims underneath. 
        //Should have done it at the IPrincipal level, but instead I created the ToAuthenticatedStandardClaimsIdentity() which returns a new authenticated ClaimsIdentity.

        var newIdentity = new CustomApplicationIdentity(viewModel.UserName);
        var cp = new ClaimsPrincipal(newIdentity.ToAuthenticatedStandardClaimsIdentity());

        var newCP = new ClaimsTransformer().Authenticate(string.Empty, cp);
        System.Web.HttpContext.Current.User = newCP;
        Thread.CurrentPrincipal = newCP;

        if (!string.IsNullOrWhiteSpace(viewModel.ReturnUrl))
        {
            return Redirect(viewModel.ReturnUrl);
        }
        return RedirectToAction("Index", "Identity");

    }
}

问题

当它重定向到 Action 时,我看到它再次触发了 Application_PostAuthenticateRequest,这非常合理。

但是,尽管之前设置了委托(delegate)人,但现在这似乎是一个空委托(delegate)人(没有名称,IsAuthenticated 设置为 false)。

我哪里出错了?

一些想法:

  • 是因为我还没有设置SessionSecurityToken吗?
  • 我是否完全遗漏了有关线程或正确设置上下文的内容?
  • 由于 UserLogin 方法在 MVC 中,我也尝试使用 Controller 上下文,但这似乎也不起作用。
  • 中间是否有其他东西干扰了它?
    • 阅读:有没有一种简单的方法可以验证旧登录系统的某些部分没有遗留和玩弄我?

最佳答案

经过大量研究(并涉足 excellent Pluralsight Course by Dominick Baier ),解决方案如下:

包罗万象的大步骤/问题

  • 我没有设置 session 身份验证 cookie,因此重定向被视为新请求,它没有看到 cookie 也没有设置主体。
  • 后来,当我使用 session 身份验证管理器时,发现 Cassini(VS 的内置调试服务器)根本没有加载 SessionAuthenticationManager
    • (IIS 和 IIS Express 做得很好)。

完整的解决方案

一步一步(同样,其中大部分归功于 Dominick 的视频):

第 1 步:将身份服务添加到配置

  • 右键单击您的项目,然后选择“添加引用...”
  • 在框架部分,选择 System.IdentityModel.Services
  • 将以下内容添加到您的 web.config 中:

(下面的完整大纲,将两个部分插入到您的 web.config 中的大纲中):

<configuration>
    <configSections>
        <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
        <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
    </configSections>
</configuration>

第二步:添加 session 认证管理器

(取决于配置设置)

在 web.config 的 system.webServer 部分,添加以下行:

  <remove name="RoleManager"/> <!--Not needed anymore in my case -->
  <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>

第 3 步:删除 Global.asax 中的 PostAuthenticate 方法

(不再需要,因为 SAM 可以检测 cookie;如果不需要,为什么要在每个请求上运行它,对吧?)

第 4 步:设置您的声明转换方法以设置身份验证 cookie

在您的 ClaimsAuthenticationManager 中添加这些行(我的名为 ClaimsTransformer)。我把它放在一个名为“EstablishSession”的单独方法中,它在我的委托(delegate)人已经转换后接受了它:

private void EstablishSession(ClaimsPrincipal transformedPrincipal)
{
    var sessionToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8));
    FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
}

因此,现在只要您转换声明,就会始终设置 cookie,这是有道理的,因为您仅在用户成功通过身份验证时才转换声明。

第 5 步:将头发稍微拉一下......

...想知道为什么 SessionAuthenticationManager 总是空的。

说真的,一切似乎都正常,而且你的配置是正确的,但如果它不是每次都为空,那就太糟糕了。单例的。时间。

第 6 步:将调试 Web 服务器切换到 IIS Express

啊哈,卡西尼(VS 调试器中的构建)似乎无法与 SessionAuthenticationManager 一起使用。

但是,IIS Express 可以。在您的项目设置中将其切换为该设置。

瞧!

现在我有了一个可用的页面。

关于c# - .Net Claims Auth——无法设置当前主体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21807535/

相关文章:

c# - 谁在 ASP.Net MVC Pipeline 中先执行?

c# - 通过 P/Invoke 使用回调和堆对象的安全方法

c# - 在 CSS 中使用 C# 变量

c# - 无法将 COM 对象转换为接口(interface)类型 'WUApiLib.UpdateSession c#

asp.net - 如何创建 ASP.NET 网站的移动版本?

asp.net - 处理来自 HttpWebRequest.GetResponse 的错误

javascript - knockout 从输入到函数的发送值

c# - 为什么无法在控件的构造函数中获取资源

c# - WriteLine 类