gpt4 book ai didi

ios - 如何正确地在 UIWebView 中进行身份验证?

转载 作者:IT王子 更新时间:2023-10-29 08:08:16 26 4
gpt4 key购买 nike

我想在我的 UIWebView 中支持 HTTP 基本身份验证。

目前,我正在取消

中的请求

webView:shouldStartLoadWithRequest:navigationType: 然后在我自己的 NSURLConnectionDelegate 中处理它们以检查并在需要时提供凭据。然后,我使用 loadData:MIMEType:textEncodingName:baseURL: 在 Web View 中显示 HTML。这适用于传递给委托(delegate)的任何 URL。

我的问题是永远不会为嵌入元素调用委托(delegate),例如图像、JavaScript 或 CSS 文件。因此,如果我有一个 HTML 页面引用了受基本身份验证保护的图像,则无法正确加载该图像。此外,永远不会调用 webView:didFinishLoad:,因为 Web View 无法完全加载页面。

我已经用 App Store 上提供的第三方浏览器 Terra 验证了这种情况,它完全可以应对这种情况。我认为可以通过提供我自己的 NSURLProtocol 来解决这个问题,但这似乎太复杂了。我错过了什么?

最佳答案

尝试对您需要验证的所有域使用 sharedCredentialStorage。

这是 UIWebView 的工作示例,它针对仅启用了 BasicAuthentication 的 Windows IIS 进行了测试

这是添加站点凭据的方法:

NSString* login = @"MYDOMAIN\\myname";
NSURLCredential *credential = [NSURLCredential credentialWithUser:login
password:@"mypassword"
persistence:NSURLCredentialPersistenceForSession];

NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"myhost"
port:80
protocol:@"http"
realm:@"myhost" // check your web site settigns or log messages of didReceiveAuthenticationChallenge
authenticationMethod:NSURLAuthenticationMethodDefault];

[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential
forProtectionSpace:protectionSpace];
[protectionSpace release];

编辑:Swift 4 中的相同代码

let login = "MYDOMAIN\\myname"
let credential = URLCredential(user:login, password:"mypassword", persistence:.forSession)
let protectionSpace = URLProtectionSpace(host:"myhost", port:80, protocol:"http", realm:"myhost", authenticationMethod:NSURLAuthenticationMethodDefault)
URLCredentialStorage.shared.setDefaultCredential(credential, for:protectionSpace)

您的 webView 现在应该可以工作了,如果它不工作,请使用下一个代码进行调试,尤其是检查 didReceiveAuthenticationChallenge 的日志消息。

    #import "TheSplitAppDelegate.h"
#import "RootViewController.h"

@implementation TheSplitAppDelegate

@synthesize window = _window;
@synthesize splitViewController = _splitViewController;
@synthesize rootViewController = _rootViewController;
@synthesize detailViewController = _detailViewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the split view controller's view to the window and display.
self.window.rootViewController = self.splitViewController;
[self.window makeKeyAndVisible];

NSLog(@"CONNECTION: Add credentials");

NSString* login = @"MYDOMAIN\\myname";
NSURLCredential *credential = [NSURLCredential credentialWithUser:login
password:@"mypassword"
persistence:NSURLCredentialPersistenceForSession];

NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"myhost"
port:80
protocol:@"http"
realm:@"myhost" // check your web site settigns or log messages of didReceiveAuthenticationChallenge
authenticationMethod:NSURLAuthenticationMethodDefault];


[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
[protectionSpace release];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://myhost/index.html"]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:12
];

NSLog(@"CONNECTION: Run request");
[[NSURLConnection alloc] initWithRequest:request delegate:self];

return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{

}

- (void)applicationDidEnterBackground:(UIApplication *)application
{

}

- (void)applicationWillEnterForeground:(UIApplication *)application
{

}

- (void)applicationDidBecomeActive:(UIApplication *)application
{

}

- (void)applicationWillTerminate:(UIApplication *)application
{

}

- (void)dealloc
{
[_window release];
[_splitViewController release];
[_rootViewController release];
[_detailViewController release];
[super dealloc];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
NSLog(@"CONNECTION: got auth challange");
NSString* message = [NSString stringWithFormat:@"CONNECTION: cred cout = %i", [[[NSURLCredentialStorage sharedCredentialStorage] allCredentials] count]];
NSLog(message);
NSLog([connection description]);

NSLog([NSString stringWithFormat:@"CONNECTION: host = %@", [[challenge protectionSpace] host]]);
NSLog([NSString stringWithFormat:@"CONNECTION: port = %i", [[challenge protectionSpace] port]]);
NSLog([NSString stringWithFormat:@"CONNECTION: protocol = %@", [[challenge protectionSpace] protocol]]);
NSLog([NSString stringWithFormat:@"CONNECTION: realm = %@", [[challenge protectionSpace] realm]]);
NSLog([NSString stringWithFormat:@"CONNECTION: authenticationMethod = %@", [[challenge protectionSpace] authenticationMethod]]);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
// release the connection, and the data object
[connection release];

// inform the user
NSLog(@"CONNECTION: failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
NSLog(@"CONNECTION: received response via nsurlconnection");
}

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection;
{
NSLog(@"CONNECTION: USE!");
return YES;
}


@end

WebView 身份验证的最终解决方案是基于自定义协议(protocol)实现。所有协议(protocol)都注册为堆栈,因此如果您重新定义 HTTP 协议(protocol),它将拦截来自 webView 的所有请求,因此您必须检查与传入请求相关的属性并将其重新打包为新请求并通过您自己的连接再次发送。由于您在堆栈中,您的请求会立即再次出现,您必须忽略它。所以它将协议(protocol)栈向下传递到真正的 HTTP 协议(protocol)实现,因为您的请求未被验证,您将获得身份验证请求。在身份验证之后,您将从服务器获得真实响应,因此您重新打包响应并回复从 webView 收到的原始请求,仅此而已。

不要尝试创建新的请求或响应主体,您必须重新发送它们。最终代码大约为 30-40 行代码,非常简单,但需要大量调试和测试。

不幸的是我不能在这里提供代码,因为我已经被分配到不同的项目,我只是想说我的帖子是错误的,当用户更改密码时它卡住了。

关于ios - 如何正确地在 UIWebView 中进行身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8999776/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com