在 ASP.NET MVC 中将 FormsIdentity 替换为 WindowsIdentity

Posted

技术标签:

【中文标题】在 ASP.NET MVC 中将 FormsIdentity 替换为 WindowsIdentity【英文标题】:Replace FormsIdentity with WindowsIdentity in ASP.NET MVC 【发布时间】:2015-03-13 14:40:00 【问题描述】:

我有一个在 Windows Phone 8.1 设备上运行的应用程序,它访问基于 ASP.NET MVC WebAPI 的后端构建。身份验证是使用 FormsAuthentication 完成的,因为在此设置中无法使用 WindowsAuthentication。我可以让它运行:用户在手机上的自定义登录表单中输入她的凭据,并在服务器端根据 Active Directory 验证凭据。之后客户端得到一个AuthenticationToken。

这个 sn-p 来自 LoginController:

if (Membership.ValidateUser(username, password))

    FormsAuthentication.SetAuthCookie(username, false);
    return Request.CreateResponse(HttpStatusCode.OK);

else
    return Request.CreateResponse(HttpStatusCode.Unauthorized);

而且这个sn -p显示了Web.Config中的认证配置:

<system.web>
  <authentication mode="Forms" />
  <authorization>
    <allow users="*" />
  </authorization>
  <membership defaultProvider="MembershipADProvider">
    <providers>
      <add name="MembershipADProvider" 
           type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
           connectionStringName="ADConnectionString"/>
    </providers>
  </membership>
</system.web>

我的问题是 FormsIdentity 只公开用户名。但后端需要一个包含 AD 用户 SID 的 WindowsIdentity。后端最初是为基于浏览器的客户端构建的,并非旨在为移动设备提供服务。

var windowsId = User.Identity as WindowsIdentity;
if (windowsId == null) return null;
var sid = windowsId.User; 

我的想法是在进行身份验证后将 FormsIdentity 替换为 WindowsIdentity。为了做到这一点,我连接到 ASP.NET 管道的 PostAuthenticateRequest 事件:

using System;
using System.Web;

namespace MyApp

    public class FromToWindowsAuthenticationModule : IHttpModule
    
        public void Init(HttpApplication context)
        
            context.PostAuthenticateRequest += PostAuthenticateRequest;
        

        public void Dispose()
        
        

        private void PostAuthenticateRequest(object sender, EventArgs e)
        
            var ctx = HttpContext.Current;
            if (ctx.Request.IsAuthenticated)
            
                var principal = ctx.User;
                var formsIdentity = principal.Identity as FormsIdentity;
                if (formsIdentity != null)
                
                    var username = formsIdentity.Name;

                    var ident = new WindowsIdentity(...);  // ???????????????????

                    var newUser = new WindowsPrincipal(ident);        
                    ctx.User = Thread.CurrentPrincipal = newUser
                
            
        
    

要激活模块,必须将这些行添加到 Web.Config:

  <system.webServer>
    <modules>
      <add name="FormToWindowsAuthenticationModule" 
           type="MyApp.FormToWindowsAuthenticationModule"
           preCondition="managedHandler" />
    </modules>
  </system.webServer>

唯一缺少的是从 ActiveDirectory 中检索 WindowsIdentifier 的部分。我该怎么做?

我的方法可行吗? Identity 对象的替换是否会干扰 ASP.NET 管道的剩余元素?

【问题讨论】:

【参考方案1】:

这看起来很有希望:

    private void PostAuthenticateRequest(object sender, EventArgs e)
    
        var ctx = HttpContext.Current;
        if (ctx.Request.IsAuthenticated)
        
            var principal = ctx.User;
            var formsIdentity = principal.Identity as FormsIdentity;
            if (formsIdentity != null)
            
                var username = formsIdentity.Name;
                var domain = "mydomain.com";
                var fullyQualifiedUsername = username + "@" + domain;

                var windowsIdentity = new WindowsIdentity(fullyQualifiedUsername);
                var windowsPrincipal = new WindowsPrincipal(windowsIdentity);

                Thread.CurrentPrincipal = ctx.User = windowsPrincipal;
            
        
    

【讨论】:

以上是关于在 ASP.NET MVC 中将 FormsIdentity 替换为 WindowsIdentity的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET MVC 中将数据传递到母版页

如何在 ASP.Net MVC 中将列表对象显示到视图中?

如何在 ASP.NET CORE 5.0 MVC 中将登录设置为默认路由

在 MVC ASP.Net 中将插件添加到部分视图选择列表

如何在 ASP.NET MVC 中将 CSS 类应用于 Html.ActionLink?

如何在 asp.net mvc4 中将 OpenID 迁移到 OAuth