Bri*_*n Y 61 asp.net authentication cookies asp.net-mvc 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.
小智 44
我有完全相同的问题,但使用另一台设备(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>
Run Code Online (Sandbox Code Playgroud)
或者更改默认值:
<browsers>
<browser refID="Default">
<capabilities>
<capability name="cookies" value="true" />
</capabilities>
</browser>
</browsers>
Run Code Online (Sandbox Code Playgroud)
更多信息:浏览器定义文件架构
Bri*_*n Y 42
我们找到的解决方案是创建一个文件(generic.browser)并包含这个xml告诉Web服务器"Mozilla"和默认浏览器设置都应该支持cookie.
<browser refID="Mozilla" >
<capabilities>
<capability name="cookies" value="true" />
</capabilities>
</browser>
Run Code Online (Sandbox Code Playgroud)
Sco*_*man 17
这在ASP.NET 4.5中已得到修复,并且假定所有浏览器都支持cookie,因此不需要额外的.browser文件.
小智 5
根据我的研究,您无法设置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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
3)调用静态方法来交换方法.我在didFinishLaunchingWithOptions中进行了这个调用:
// Need to call this method so that User-Agent get updated correctly:
[NSMutableURLRequest setupUserAgentOverwrite];
Run Code Online (Sandbox Code Playgroud)
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];
}
Run Code Online (Sandbox Code Playgroud)