簡體   English   中英

使用iPhone UIWebView時的Asp.Net Forms身份驗證

[英]Asp.Net Forms Authentication when using iPhone UIWebView

我正在編寫一個使用表單身份驗證的Asp.net MVC 2應用程序,目前我的iPhone應用程序在通過Web進行身份驗證/登錄時遇到問題。 我們開發了一個使用UIWebView控件的簡單iPhone應用程序。 在這個階段,所有應用程序都會導航到我們的Asp.Net網站。 簡單吧? 問題是,用戶無法通過登錄頁面。 重復步驟是:

  • 打開iPhone應用程序。
  • 該應用程序導航到主頁。
  • 用戶未經過身份驗證,因此會重定向到登錄屏幕/頁面
  • 用戶輸入正確的用戶名和密碼。 點擊提交。
  • 在服務器端,用戶經過身份驗證,並生成cookie並使用FormsAuthentication.GetAuthCookie發送到客戶端。
  • 服務器發送是重定向以將用戶發送到正確的主頁。

但是用戶然后被重定向到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。

解:

  1. 在Web項目中添加名為App_Browsers的文件夾(右鍵單擊該項目,選擇: Add > Add ASP.NET Folder > App_Browsers )。
  2. 在該文件夾中添加文件(右鍵單擊,選擇: Add > New Item )。 該文件可以具有任何名稱,但必須具有.browser結尾。
  3. 添加一個良好的匹配表達式和正確的功能(或添加對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來處理它。

  1. 您是否在標記中指定了DestinationPageUrl?

  2. 您是否在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是否真的存在?

UIWebView的cookie存儲在哪里?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM