Asp.net-Mvc

WebAPI + Forms Authentication + SimpleMembershipProvider 在不應該使用 WindowsIdentity 時使用

  • April 14, 2013

我做了什麼

我正在建構一個 REST 風格的 WebAPI 應用程序。我正在嘗試在這裡實現表單身份驗證,因此客戶端可以允許使用者從瀏覽器登錄/註冊/註銷。我正在使用 simpleMembership,使用者儲存在我的應用程序的 simpleMembership 數據庫表中。作為第一步,我在我的 AccountsController 中實現了一個登錄方法:

   [System.Web.Http.HttpPost]
   public HttpResponseMessage LogIn(LoginModel model)
   {
       if (ModelState.IsValid)
       {
           if (User.Identity.IsAuthenticated)
           {
               return Request.CreateResponse(HttpStatusCode.Conflict, "already logged in.");
           }
           if (WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
           {
               FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
               //TODO: look up by id, not by name
               var userProfile = _service.GetUser(WebSecurity.GetUserId(model.UserName));
               return Request.CreateResponse(HttpStatusCode.OK, userProfile);
           }
           else
           {
               return new HttpResponseMessage(HttpStatusCode.Unauthorized);
           }
       }

       // If we got this far, something failed
       return new HttpResponseMessage(HttpStatusCode.InternalServerError);
   }

問題

這是正在發生的事情:

  1. 我在if (User.Identity.IsAuthenticated).
  2. 使用 POSTMan 或 Fiddler 之類的東西,我嘗試使用一些偽造的憑據登錄。
  3. 正如預期的那樣,我打斷點並為 IsAuthenticated 獲得“假”。
  4. 我跳到下一個“如果”,嘗試登錄失敗,正如預期的那樣。
  5. 語句中的程式碼else被命中,但一旦返回,1)我的斷點再次被命中,2)主體設置為我的 windows 身份。兩者都是出乎意料的,我正試圖弄清楚如何糾正它。

在此處輸入圖像描述

預期行為

  • 該方法只返回 401 Unauthorized,因為我的應用程序數據庫中不存在虛假使用者。

配置

認為這是一個配置問題 - 在身份驗證失敗時,由於某種原因,主體會自動設置為我的 Windows 帳戶。與我的配置相關的一些細節:

<authentication mode="Forms">
 <forms loginUrl="~/" timeout="2880" />
</authentication>
  • 我沒有在應用程序的任何地方啟用 Windows 身份驗證。我的 web.config 在上面 ^
  • 使用 IISManager 我已禁用匿名身份驗證
  • 在我的 applicationhost.config 中,我禁用了 Windows 和匿名身份驗證

問題

  1. 為什麼斷點被擊中兩次,而不是 LogIn 方法只返回 Unauthorized ,因為最後一個“else”被擊中?
  2. 為什麼我的 Windows 憑據被用於這個意外和不希望的“環回”?
  3. 我怎樣才能防止這種情況發生?或者:
  4. 我需要使用 MessageHandler 來設置主體嗎?如果是這樣,這將如何影響$$ Authenticate $$和IsAuthenticated?有什麼例子嗎?

更新 1

我嘗試註冊以下處理程序:

public class PrincipalHandler : DelegatingHandler
   {

       protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
                                                                              System.Threading.CancellationToken
                                                                                  cancellationToken)
       {
           HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
           Thread.CurrentPrincipal = HttpContext.Current.User;
           return await base.SendAsync(request, cancellationToken);
       }

   }

現在主體從未設置為我的 Windows 身份。從 POSTMan(瀏覽器擴展),if 語句被擊中兩次,我得到一個彈出視窗,要求提供憑據。正如預期的那樣,從 Fiddler 那裡,我得到了 401 Unauthorized。

新問題

  1. 如何根據響應 cookie 中的內容設置主體,並針對我的應用程序的簡單成員表進行身份驗證?

更新 2

這篇文章似乎讓我朝著正確的方向前進——在我的 LoginMethod 中使用 Membership 而不是 User:

ASP.NET MVC - 設置自定義 IIdentity 或 IPrincipal

將繼續更新進展,但我仍然願意接受建議/建議。

更新 3 我從來沒有像現在這樣既放鬆又生氣——這裡不需要自定義處理程序。我的項目屬性中啟用了 Windows 身份驗證。登錄和註銷的工作解決方案在這裡,並且與我的會員表“一起工作”:

public HttpResponseMessage LogIn(LoginModel model)
       {
           if (ModelState.IsValid)
           {
               if (User.Identity.IsAuthenticated)
               {
                   return Request.CreateResponse(HttpStatusCode.Conflict, "already logged in.");
               }
               if (WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
               {
                   FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                   return Request.CreateResponse(HttpStatusCode.OK, "logged in successfully");
               }
               else
               {
                   return new HttpResponseMessage(HttpStatusCode.Unauthorized);
               }
           }

           // If we got this far, something failed
           return new HttpResponseMessage(HttpStatusCode.InternalServerError);
       }

public HttpResponseMessage LogOut()
       {
           if (User.Identity.IsAuthenticated)
           {
               WebSecurity.Logout();
               return Request.CreateResponse(HttpStatusCode.OK, "logged out successfully.");
           }
           return Request.CreateResponse(HttpStatusCode.Conflict, "already done.");
       }

您是否使用 IIS Express 進行開發?如果是這樣,請在 Visual Studio 中點擊您的項目並檢查屬性視窗。這裡有一個用於 Windows 身份驗證的選項,我相信它預設是啟用的。在這裡也禁用它。

引用自:https://stackoverflow.com/questions/15994857