[英]Asp.Net Forms Authentication when using iPhone UIWebView
我正在編寫一個使用表單身份驗證的Asp.net MVC 2應用程序,目前我的iPhone應用程序在通過Web進行身份驗證/登錄時遇到問題。 我們開發了一個使用UIWebView控件的簡單iPhone應用程序。 在這個階段,所有應用程序都會導航到我們的Asp.Net網站。 簡單吧? 問題是,用戶無法通過登錄頁面。 重復步驟是:
但是用戶然后被重定向到BACK登錄屏幕!
我已經對此進行了一些廣泛的調試,我所知道的是:
cookie被發送到客戶端,客戶端正在存儲cookie。 在iPhone調試器中驗證了這一點,並使用Javsascript在頁面上顯示cookie數據。 cookie正被發送回服務器。 在Visual Studio調試器中驗證了這一點。 它是正確的cookie(它與設置的相同)。 User.Identity.IsAuthenticated屬性由於某種原因返回false,即使auth cookie包含在Request對象中。 我已經確認iPhone應用程序已設置為接受cookie,並且它們在客戶端上。
這是有趣的事情:如果您在iPhone上打開Safari瀏覽器並直接訪問我們的網站,它可以正常工作。
它在iPad上也具有相同的行為,因為它沒有通過登錄屏幕。 這種模擬器和設備上的重復。
這個網站已經通過IE 7-8,Safari(適用於Windows),Blackberry,IEMobile 6.5,Phone 7進行了測試,可以找到它。 唯一不適用的情況是iPhone應用程序中的UIWebView。
我有完全相同的問題,但使用另一台設備(NokiaN8),並將問題追溯到User-Agent。
IIS使用正則表達式來匹配User-Agent字符串。 該問題的根源在於它沒有特定設備的任何匹配正則表達式,最終處於使用默認屬性的最低匹配級別之一。 默認屬性表示瀏覽器不支持cookie。
解:
App_Browsers
的文件夾(右鍵單擊該項目,選擇: Add > Add ASP.NET Folder > App_Browsers
)。 Add > New Item
)。 該文件可以具有任何名稱,但必須具有.browser
結尾。 Default
更改)。 兩個例子:
<browsers>
<browser id="NokiaN8" parentID="Mozilla">
<identification>
<userAgent match="NokiaN8" />
</identification>
<capabilities>
<capability name="browser" value="NokiaN8" />
<capability name="cookies" value="true" />
</capabilities>
</browser>
</browsers>
或者更改默認值:
<browsers>
<browser refID="Default">
<capabilities>
<capability name="cookies" value="true" />
</capabilities>
</browser>
</browsers>
更多信息: 瀏覽器定義文件架構
我們找到的解決方案是創建一個文件(generic.browser)並包含這個xml來告訴Web服務器“Mozilla”和默認瀏覽器設置都應該支持cookie。
<browser refID="Mozilla" >
<capabilities>
<capability name="cookies" value="true" />
</capabilities>
</browser>
這在ASP.NET 4.5中已得到修復,並且假定所有瀏覽器都支持cookie,因此不需要額外的.browser文件。
根據我的研究,您無法設置User-Agent的原因是UIWebView在發出請求之前就設置了User-Agent值,也就是說,在您從代碼發出請求之后。
解決這個問題的訣竅是使用一種稱為“方法調配”的東西,這是一種先進的,具有潛在危險的Objective-C概念,可以用您提供的方法交換標准方法。 最終結果是,當您的請求被發出並且框架代碼添加了User-Agent時,它將被使用您提供的方法欺騙。
以下解釋了我為實現這一點所做的工作,但我不是Objective-C專家,建議您做一些研究以熟悉該技術。 特別是,那里有一個鏈接比我更好地解釋了這里發生了什么,但目前我找不到它。
1)在NSObject上添加一個類別以允許調配。
@interface NSObject (Swizzle)
+ (BOOL) swizzleMethod:(SEL)origSelector withMethod:(SEL)newSelector;
@end
@implementation NSObject (Swizzle)
+ (BOOL) swizzleMethod:(SEL) origSelector withMethod:(SEL)newSelector
{
Method origMethod= class_getInstanceMethod(self, origSelector);
Method newMethod= class_getInstanceMethod(self, newSelector);
if (origMethod && newMethod)
{
if (class_addMethod(self, origSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
{
class_replaceMethod(self, newSelector, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
}
else {
method_exchangeImplementations(origMethod, newMethod);
}
return YES;
}
return NO;
}
@end
2)子類NSMutableURLRequest允許swizzle:
@interface NSMutableURLRequest (MyMutableURLRequest)
+ (void) setupUserAgentOverwrite;
@end
@implementation NSMutableURLRequest (MyMutableURLRequest)
- (void) newSetValue:(NSString*)value forHTTPHeaderField:(NSString*)field
{
if ([field isEqualToString:@"User-Agent"])
{
value = USER_AGENT; // ie, the value I want to use.
}
[self newSetValue:value forHTTPHeaderField:field];
}
+ (void) setupUserAgentOverwrite
{
[self swizzleMethod:@selector(setValue:forHTTPHeaderField:)
withMethod:@selector(newSetValue:forHTTPHeaderField:)];
}
@end
3)調用靜態方法來交換方法。 我在didFinishLaunchingWithOptions中進行了這個調用:
// Need to call this method so that User-Agent get updated correctly:
[NSMutableURLRequest setupUserAgentOverwrite];
4)然后像這樣使用它。 (連接委托將數據保存在可變數組中,然后在完成加載時使用其loadData方法手動設置UIWebView)。
- (void)loadWithURLString:(NSString*)urlString
{
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
_connection = [NSURLConnection connectionWithRequest:request delegate:self];
[_connection start];
}
我有同樣的問題,研究並整合了一個完整的解決方案(來自上面的答案和其他線程): http : //www.bloggersworld.com/index.php/asp-net-forms-authentication-iphone-cookies/
發生這種情況的原因顯然與以下事實有關:如果用戶代理未知,則假定瀏覽器不接受cookie(正如其他人已經回答的那樣),而IIS將ASPXAUTH值放入URL中。
然而,MVC路由系統顯然錯過了這種可能性,這顯然是一個錯誤,因此它變得混亂。
雖然添加.browser與自定義用戶代理解決了問題,但它並不能保證其他用戶代理也會得到解決,事實上我發現Android的K9瀏覽器也有這個問題,因此它如果有一個像elmeh這樣的記錄系統來追蹤這些錯誤,那么這只是一個解決方案。
另一方面,如果所有瀏覽器都接受cookie,那么添加默認值會提出問題,這顯然是IIS不這樣做的原因。
然而,除了明確地添加用戶代理之外,還可以在global.asax RegiterRoutes()方法中添加一個顯式處理程序來忽略它,如下所示:
routes.MapRoute(
"CookieLess", // Route name
"(F({Cookie}))/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
但是在這種情況下,除非要編寫自定義路由處理程序,否則必須復制所有路徑條目以匹配無cookie情況。
或者我們可以使用上面的無cookie路由將用戶發送到錯誤頁面,說明他的瀏覽器目前不受支持,並向用戶代理發送警報給web-master來處理它。
您是否在標記中指定了DestinationPageUrl?
您是否在web.config中指定了defaultURL?
示例web.config
<authentication mode="Forms">
<forms loginUrl="~/Login.aspx" defaultUrl="~/CustomerArea/Default.aspx"/>
</authentication>
示例DestinationPageUrl
<asp:Login ID="Login" runat="server" DestinationPageUrl="~/Secret/Default.aspx" />
最后你看過餅干罐,看看你的會話cookie是否真的存在?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.