在WKWebview中设置用户代理

60

如何在WKWebView中设置自定义用户代理字符串?我试图嵌入我的应用程序的版本,以便我的服务器端可以查看可用的功能。我发现了以下方法:

let userAgent = "MyApp/1.33.7"
request.setValue(userAgent, forHTTPHeaderField: "User-Agent")

NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
    let content = NSString(data: data, encoding: NSUTF8StringEncoding)
    self.web!.loadHTMLString(content!, baseURL: url)
}
self.web!.loadRequest(request);
但这意味着useragent仅针对该单个请求进行设置。第一个其他请求(例如前向请求)将意味着useragent再次重置为默认设置。我如何更永久地配置wkwebview以使用我的自定义useragent字符串?

请使用此处描述的与UIWebView相同的方法:https://dev59.com/LHRB5IYBdhLWcg3w4bKv - Nikola Lajic
这确实有一个不错的解决方案,使用默认字典似乎很有效 :-) 我唯一不确定的是如何从WKWebView获取现有的userAgent字符串。对此有什么想法吗? - Pvel
可能是WKWebview设置用户代理OS X Yosemite的重复问题。 - jrc
6个回答

99
你会高兴地听到,在iOS 9和OSX 10.11中,WKWebView刚刚新增了一个customUserAgent属性。
示例:
wkWebView.customUserAgent = "your agent" 

6
@haykam 是的,wkWebView.customUserAgent = "你的代理" - Robert
你也可以将其附加到它上面而不改变整个内容,参见Marián Černý的回答 - h3dkandi

36

更新:

从iOS 9.0开始,可以直接设置用户代理(如其他答案所述)。但是需要注意的是,设置后将完全覆盖默认的用户代理。如果您只需要添加自定义用户代理,请使用以下方法之一。

webView.evaluateJavaScript("navigator.userAgent") { [weak webView] (result, error) in
    if let webView = webView, let userAgent = result as? String {
        webView.customUserAgent = userAgent + "/Custom Agent"
    }
}

或者通过使用牺牲性的UIWebView

webView.customUserAgent = (UIWebView().stringByEvaluatingJavaScript(from: "navigator.userAgent") ?? "") + "/Custom agent"


旧答案:

如我的评论中所述,您可以使用与此处描述的相同方法: Change User Agent in UIWebView (iPhone SDK)

现在,如果您想获取用户代理,则需要拥有 WKWebView 的实例并在其上评估此 JavaScript:


如果您想获取用户代理,您可以按照这篇文章中提到的方法来改变UIWebView的用户代理。

要获取用户代理,您需要创建一个WKWebView实例并在其上运行以下JavaScript代码:

navigator.userAgent

问题在于,如果在WKWebView实例化后设置自定义用户代理,则始终会获取相同的用户代理。要解决此问题,您必须重新实例化Web视图。以下是可能的示例:

self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];
__weak typeof(self) weakSelf = self;

[self.wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
    __strong typeof(weakSelf) strongSelf = weakSelf;

    NSString *userAgent = result;
    NSString *newUserAgent = [userAgent stringByAppendingString:@" Appended Custom User Agent"];

    NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, @"UserAgent", nil];
    [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];

    strongSelf.wkWebView = [[WKWebView alloc] initWithFrame:strongSelf.view.bounds];

    // After this point the web view will use a custom appended user agent
    [strongSelf.wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
        NSLog(@"%@", result);
    }];
}];

以上代码将记录以下内容:

Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12B411 Appended Custom User Agent

替代方案

为了使其更简单,可以使用“牺牲性”UIWebView,因为它可以同步地评估javascript。

UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
NSString *userAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
NSString *newUserAgent = [userAgent stringByAppendingString:@" Appended Custom User Agent"];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, @"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];

self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[self.wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
    NSLog(@"%@", result);
}];

哪个记录了相同的内容:

Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12B411 Appended Custom User Agent

目前UIWebView和WKWebView使用相同的用户代理,但如果将来更改可能会导致问题。


另一种方式更加优雅。 - walker
3
在 iOS 10.3.3 上,我可以更改 customUserAgent 并且不需要重新实例化 WKWebView 就能生效。 - user2067021

24

自定义用户代理

要设置自定义的用户代理,您可以使用 customUserAgent 属性:

let webConfiguration = WKWebViewConfiguration()
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.customUserAgent = "ExampleApp/1.0 (iPhone)"

可用:iOS 9+

追加到默认用户代理

要在默认用户代理的末尾附加自定义字符串,您可以使用applicationNameForUserAgent属性:

let webConfiguration = WKWebViewConfiguration()
webConfiguration.applicationNameForUserAgent = "ExampleApp/1.0 (iPhone)"
let webView = WKWebView(frame: .zero, configuration: webConfiguration)

那么它将会像这样:

Mozilla/5.0 (iPhone; CPU iPhone OS 11_2 like Mac OS X) AppleWebKit/604.4.7
(KHTML, like Gecko) ExampleApp/1.0 (iPhone)
                    ^^^^^^^^^^^^^^^^^^^^^^^

可用性:iOS 9+


我查看了你的解决方案,并按照描述设置了webConfiguration.applicationNameForUserAgent。但是在设置后,它只打印出ExampleApp/1.0 (iPhone),而不是整个字符串Mozilla/5.0 (iPhone; CPU iPhone OS 11_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) ExampleApp/1.0 (iPhone) - Tejas
如果您想以编程方式构建您的应用程序名称,您可以执行以下操作:NSDictionary *bundleInfo = [NSBundle mainBundle].infoDictionary; NSString *applicationName = bundleInfo[(NSString *)kCFBundleNameKey]; NSString *build = bundleInfo[(NSString *)kCFBundleVersionKey]; NSString *deviceModel = [[UIDevice currentDevice] model]; NSString *myApplicatiopnNameForUserAgent = [NSString stringWithFormat:@"%@/%@ (%@)", applicationName, build, deviceModel];如果有人能将其翻译成Swift并添加到答案中,那就太好了。 - h3dkandi

2

WKWebView中的默认User-Agent如下:

Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X)

您可以自定义WKWebView的用户代理。
webView.customUserAgent = "zgpeace User-Agent"

我为WKWebView编写了一个演示:

func requestWebViewAgent() {
        print("requestWebViewAgent")

        let webView = WKWebView()
        webView.evaluateJavaScript("navigator.userAgent") { (userAgent, error) in
            if let ua = userAgent {
                print("default WebView User-Agent > \(ua)")
            }

            // customize User-Agent
            webView.customUserAgent = "zgpeace User-Agent"
        }
    }

警告:当webView被释放时,“User-Agent”为空。您可以将webView对象设置为属性以保留webView。

NSURLSession默认发送User-Agent
默认的User-Agent样式如下。

"User-Agent" = "UserAgentDemo/1 CFNetwork/1121.2.1 Darwin/19.2.0";

我们可以自定义用户代理。
let config = URLSessionConfiguration.default
config.httpAdditionalHeaders = ["User-Agent": "zgpeace User-Agent"]

我写了一个下面的URLSession演示。
     func requestUrlSessionAgent() {
        print("requestUrlSessionAgent")

        let config = URLSessionConfiguration.default
        // default User-Agent: "User-Agent" = "UserAgentDemo/1 CFNetwork/1121.2.1 Darwin/19.2.0";
        // custom User-Agent
        config.httpAdditionalHeaders = ["User-Agent": "zgpeace User-Agent"]
        let session = URLSession(configuration: config)

        let url = URL(string: "https://httpbin.org/anything")!
        var request = URLRequest(url: url)
        request.httpMethod = "GET"

        let task = session.dataTask(with: url) { data, response, error in

            // ensure there is no error for this HTTP response
            guard error == nil else {
                print ("error: \(error!)")
                return
            }

            // ensure there is data returned from this HTTP response
            guard let content = data else {
                print("No data")
                return
            }

            // serialise the data / NSData object into Dictionary [String : Any]
            guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] else {
                print("Not containing JSON")
                return
            }

            print("gotten json response dictionary is \n \(json)")
            // update UI using the response here
        }

        // execute the HTTP request
        task.resume()

    }

NSURLConnection默认发送User-Agent
默认的User-Agent样式如下:

"User-Agent" = "UserAgentDemo/1 CFNetwork/1121.2.1 Darwin/19.2.0";

我们可以自定义用户代理。
urlRequest.setValue("URLConnection zgpeace User-Agent", forHTTPHeaderField: "User-Agent")

我写了一个URLConnection的演示,如下所示。
func requestUrlConnectionUserAgent() {
    print("requestUrlConnectionUserAgent")

    let url = URL(string: "https://httpbin.org/anything")!
    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "GET"
    // default User-Agent: "User-Agent" = "UserAgentDemo/1 CFNetwork/1121.2.1 Darwin/19.2.0";
    urlRequest.setValue("URLConnection zgpeace User-Agent", forHTTPHeaderField: "User-Agent")

    NSURLConnection.sendAsynchronousRequest(urlRequest, queue: OperationQueue.main) { (response, data, error) in
        // ensure there is no error for this HTTP response
        guard error == nil else {
            print ("error: \(error!)")
            return
        }

        // ensure there is data returned from this HTTP response
        guard let content = data else {
            print("No data")
            return
        }

        // serialise the data / NSData object into Dictionary [String : Any]
        guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] else {
            print("Not containing JSON")
            return
        }

        print("gotten json response dictionary is \n \(json)")
        // update UI using the response here
    }

  }

在github上的演示:
https://github.com/zgpeace/UserAgentDemo.git

该演示展示了用户代理的相关知识。

2

WKWebView 的 Swift 3 示例:

let userAgentValue = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4"
webView.customUserAgent = userAgentValue

对于那些试图在Storyboard或Interface Builder中使用的人来说,需要注意:目前(截至Xcode 8.3.2版本)Xcode不支持在Storyboard中使用WKWebView,所以你必须在代码中手动添加web视图。

UIWebView的Swift 3示例:

UserDefaults.standard.register(defaults: ["UserAgent": userAgentValue])

0
在我的 Swift 3 中,我需要整个应用程序使用自定义 userAgent,这是我的 AppDelegate 中的解决方案。这里使用 UIWebview 是因为我不需要设置 WKWebViewConfiguration,因为我只需要 userAgent 字符串。
 fileprivate func setupGlobalWebviewUserAgent() {

    let webview = UIWebView()
    var newUserAgent = webview.stringByEvaluatingJavaScript(from: "navigator.userAgent")
    newUserAgent = newUserAgent?.appending("custom user agent")
    let dictionary = Dictionary(dictionaryLiteral: ("UserAgent", newUserAgent))
    UserDefaults.standard.register(defaults: dictionary)
}

1
这与 wkWebView 无关。:( - Karthik Kumar
@KarthikKumar UserDefaults.standard 对于 UIWebViewWKWebView 都是有效的。 - DawnSong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接