面试题答案
一键面试安全风险及解决方案
- 证书验证风险
- 风险:如果不严格验证服务器证书,中间人攻击者可能伪造证书,拦截并篡改通信内容。
- 解决方案:在
WKWebView
的WKNavigationDelegate
协议方法webView:didReceiveAuthenticationChallenge:completionHandler:
中,进行证书验证。例如:
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
BOOL isValid = NO;
CFErrorRef error = NULL;
isValid = SecTrustEvaluateWithError(serverTrust, &error);
if (isValid) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
}
}
- 跨站脚本攻击(XSS)风险
- 风险:恶意脚本可能被注入到加载的页面中,窃取用户数据或执行其他恶意操作。
- 解决方案:对加载的内容进行严格的输入验证和过滤,避免使用
WKWebView
的stringByEvaluatingJavaScriptFromString:
等方法执行不可信的JavaScript代码。同时,设置WKWebView
的configuration.preferences.javaScriptEnabled
为NO
可以完全禁用JavaScript执行,但这可能影响页面正常功能,所以需要谨慎评估。
- 跨站请求伪造(CSRF)风险
- 风险:攻击者可能利用用户已登录的状态,伪造请求,在用户不知情的情况下执行操作。
- 解决方案:服务器端应使用CSRF令牌机制,每次请求都带上随机生成且与用户会话相关联的令牌,服务器验证令牌的有效性。客户端在发起请求时,确保从服务器获取并正确携带令牌。
性能优化思路
- 减少加载时间
- 预加载:在需要加载
WKWebView
之前,提前创建WKWebView
实例并开始加载页面,例如在视图控制器的viewDidLoad
方法中开始加载。 - 缓存策略:合理设置
NSURLRequest
的缓存策略,如NSURLRequestReturnCacheDataElseLoad
,优先从本地缓存加载数据,减少网络请求。
- 预加载:在需要加载
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:15.0];
[webView loadRequest:request];
- **优化资源大小**:服务器端对图片、脚本等资源进行压缩,减少传输数据量。同时,避免加载不必要的资源,如通过优化HTML和CSS,减少重排和重绘。
2. 降低内存占用
- 及时释放资源:在 WKWebView
不再使用时,如视图控制器即将销毁时,释放相关资源。可以调用 [webView.configuration.userContentController removeScriptMessageHandlers];
移除脚本消息处理程序,并将 webView
设置为 nil
。
- 限制图片加载:可以通过JavaScript注入的方式,在页面加载时限制图片的加载数量或尺寸,避免一次性加载大量高清图片导致内存飙升。例如,通过注入如下JavaScript代码:
NSString *script = @"document.documentElement.style.webkitTouchCallout='none'; document.documentElement.style.webkitUserSelect='none'; document.documentElement.style.MozUserSelect='none'; document.documentElement.style.msUserSelect='none'; document.documentElement.style.userSelect='none'; var images = document.getElementsByTagName('img'); for (var i = 0; i < images.length; i++) { if (images[i].width > 200) { images[i].width = 200; } }";
WKUserScript *userScript = [[WKUserScript alloc] initWithSource:script injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
[webView.configuration.userContentController addUserScript:userScript];
- **分页加载**:对于长页面,采用分页加载的方式,每次只加载部分内容,减少一次性加载的内容量,从而降低内存占用。