首页 文章

使用iPhone UIWebView时的Asp.Net Forms身份验证

提问于
浏览
61

我正在编写一个使用表单身份验证的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 .

7 回答

  • 0

    我有完全相同的问题,但使用另一台设备(NokiaN8),并将问题追溯到User-Agent .

    IIS使用正则表达式来匹配User-Agent字符串 . 该问题的根源在于它没有特定设备的任何匹配正则表达式,最终处于使用默认属性的最低匹配级别之一 . 默认属性表示浏览器不支持cookie .

    Solution:

    • 在Web项目中添加名为 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>
    

    更多信息:浏览器定义文件架构

  • 3

    我们找到的解决方案是创建一个文件(generic.browser)并包含这个xml告诉Web服务器“Mozilla”和默认浏览器设置都应该支持cookie .

    <browser refID="Mozilla" >
        <capabilities>
            <capability name="cookies"  value="true" />
        </capabilities>
    </browser>
    
  • 4

    这在ASP.NET 4.5中已得到修复,并且假定所有浏览器都支持cookie,因此不需要额外的.browser文件 .

  • 44

    根据我的研究,您无法设置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];
    }
    
  • 42

    我有同样的问题,研究并整合了一个完整的解决方案(来自上面的答案和其他线程):http://www.bloggersworld.com/index.php/asp-net-forms-authentication-iphone-cookies/

  • 17
    • 您是否在标记中指定了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" />
    

    最后你看过 Cookies jar ,看看你的会话cookie是否真的存在?

    Where are an UIWebView's cookies stored?

  • 0

    发生这种情况的原因显然与以下事实有关:如果用户代理未知,则假定浏览器不接受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来处理它 .

相关问题