關閉一個子目錄的 ASP.Net WebForms 身份驗證
我有一個包含 WebForms 和 MVC 頁面的大型企業應用程序。它具有我不想更改的現有身份驗證和授權設置。
WebForms 身份驗證在 web.config 中配置:
<authentication mode="Forms"> <forms blah... blah... blah /> </authentication> <authorization> <deny users="?" /> </authorization>到目前為止相當標準。我有一個 REST 服務,它是這個大型應用程序的一部分,我想對這個服務使用 HTTP 身份驗證。
因此,當使用者嘗試從 REST 服務獲取 JSON 數據時,它會返回 HTTP 401 狀態和
WWW-Authenticate標頭。如果他們以正確格式的 HTTPAuthorization響應進行響應,它將允許他們進入。問題是 WebForms 在低級別覆蓋了它 - 如果您返回 401(未經授權),它會用 302(重定向到登錄頁面)覆蓋它。這在瀏覽器中很好,但對 REST 服務無用。
我想關閉 web.config 中的身份驗證設置,覆蓋“rest”文件夾:
<location path="rest"> <system.web> <authentication mode="None" /> <authorization><allow users="?" /></authorization> </system.web> </location>授權位工作正常,但身份驗證行 (
<authentication mode="None" />) 會導致異常:在應用程序級別之外使用註冊為 allowDefinition=‘MachineToApplication’ 的部分是錯誤的。
我在應用程序級別配置它 - 它在根 web.config 中 - 並且該錯誤是針對子目錄中的 web.configs 的。
如何覆蓋身份驗證,以便站點的所有其餘部分都使用 WebForms 身份驗證,而這個目錄不使用任何身份驗證?
這類似於另一個問題:401 response code for json requests with ASP.NET MVC,但我不是在尋找相同的解決方案 - 我不想只是刪除 WebForms 身份驗證並在全域範圍內添加新的自定義程式碼,還有很遠涉及很多風險和工作。我只想更改配置中的一個目錄。
更新
我想設置一個 Web 應用程序,並且我希望所有 WebForms 頁面和 MVC 視圖都使用 WebForms 身份驗證。我希望一個目錄使用基本的 HTTP 身份驗證。
請注意,我說的是身份驗證,而不是授權。我希望 REST 呼叫帶有 HTTP 標頭中的使用者名和密碼,並且我希望 WebForm 和 MVC 頁面帶有來自 .Net 的身份驗證 cookie - 在任何一種情況下,授權都是針對我們的數據庫進行的。
我不想重寫 WebForms 身份驗證並滾動我自己的 cookie - 這是將 HTTP 授權的 REST 服務添加到應用程序的唯一方法似乎很荒謬。
我不能添加額外的應用程序或虛擬目錄 - 它必須作為一個應用程序。
我已經以混亂的方式解決了這個問題 - 通過在 global.asax 中為所有現有頁面欺騙 Forms 身份驗證。
我仍然沒有完全工作,但它是這樣的:
protected void Application_BeginRequest(object sender, EventArgs e) { // lots of existing web.config controls for which webforms folders can be accessed // read the config and skip checks for pages that authorise anon users by having // <allow users="?" /> as the top rule. // check local config var localAuthSection = ConfigurationManager.GetSection("system.web/authorization") as AuthorizationSection; // this assumes that the first rule will be <allow users="?" /> var localRule = localAuthSection.Rules[0]; if (localRule.Action == AuthorizationRuleAction.Allow && localRule.Users.Contains("?")) { // then skip the rest return; } // get the web.config and check locations var conf = WebConfigurationManager.OpenWebConfiguration("~"); foreach (ConfigurationLocation loc in conf.Locations) { // find whether we're in a location with overridden config if (this.Request.Path.StartsWith(loc.Path, StringComparison.OrdinalIgnoreCase) || this.Request.Path.TrimStart('/').StartsWith(loc.Path, StringComparison.OrdinalIgnoreCase)) { // get the location's config var locConf = loc.OpenConfiguration(); var authSection = locConf.GetSection("system.web/authorization") as AuthorizationSection; if (authSection != null) { // this assumes that the first rule will be <allow users="?" /> var rule = authSection.Rules[0]; if (rule.Action == AuthorizationRuleAction.Allow && rule.Users.Contains("?")) { // then skip the rest return; } } } } var cookie = this.Request.Cookies[FormsAuthentication.FormsCookieName]; if (cookie == null || string.IsNullOrEmpty(cookie.Value)) { // no or blank cookie FormsAuthentication.RedirectToLoginPage(); } // decrypt the var ticket = FormsAuthentication.Decrypt(cookie.Value); if (ticket == null || ticket.Expired) { // invalid cookie FormsAuthentication.RedirectToLoginPage(); } // renew ticket if needed var newTicket = ticket; if (FormsAuthentication.SlidingExpiration) { newTicket = FormsAuthentication.RenewTicketIfOld(ticket); } // set the user so that .IsAuthenticated becomes true // then the existing checks for user should work HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(newTicket), newTicket.UserData.Split(',')); }我對此不太滿意——這似乎是一個可怕的黑客和輪子的重新發明,但看起來這是我的表單認證頁面和 HTTP 認證 REST 服務工作的唯一方法相同的應用程序。
如果“rest”只是根目錄中的一個文件夾,那麼您幾乎就在那裡:刪除身份驗證行,即
<location path="rest"> <system.web> <authorization> <allow users="*" /> </authorization> </system.web> </location>或者,您可以將 web.config 添加到您的 rest 文件夾中,然後就可以了:
<system.web> <authorization> <allow users="*" /> </authorization> </system.web>檢查這個。