Asp.net-Mvc
WebAPI + Forms Authentication + SimpleMembershipProvider 在不應該使用 WindowsIdentity 時使用
我做了什麼
我正在建構一個 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); }問題
這是正在發生的事情:
- 我在
if (User.Identity.IsAuthenticated).- 使用 POSTMan 或 Fiddler 之類的東西,我嘗試使用一些偽造的憑據登錄。
- 正如預期的那樣,我打斷點並為 IsAuthenticated 獲得“假”。
- 我跳到下一個“如果”,嘗試登錄失敗,正如預期的那樣。
- 語句中的程式碼
else被命中,但一旦返回,1)我的斷點再次被命中,2)主體設置為我的 windows 身份。兩者都是出乎意料的,我正試圖弄清楚如何糾正它。
預期行為
- 該方法只返回 401 Unauthorized,因為我的應用程序數據庫中不存在虛假使用者。
配置
我認為這是一個配置問題 - 在身份驗證失敗時,由於某種原因,主體會自動設置為我的 Windows 帳戶。與我的配置相關的一些細節:
<authentication mode="Forms"> <forms loginUrl="~/" timeout="2880" /> </authentication>
- 我沒有在應用程序的任何地方啟用 Windows 身份驗證。我的 web.config 在上面 ^
- 使用 IISManager 我已禁用匿名身份驗證
- 在我的 applicationhost.config 中,我禁用了 Windows 和匿名身份驗證
問題
- 為什麼斷點被擊中兩次,而不是 LogIn 方法只返回 Unauthorized ,因為最後一個“else”被擊中?
- 為什麼我的 Windows 憑據被用於這個意外和不希望的“環回”?
- 我怎樣才能防止這種情況發生?或者:
- 我需要使用 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。
新問題
- 如何根據響應 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 身份驗證的選項,我相信它預設是啟用的。在這裡也禁用它。
