NSURLSession是否自动发送用户代理

Yas*_*kin 3 user-agent nsurlsession watchkit ios9

用户WatchKit 2.0,iOS 9.0时,NSURLSession会自动发送用户代理吗?有没有办法在WatchKit应用程序中验证这一点?

Zgp*_*ace 6

NSURLSession 默认发送 User-Agent
默认的 User-Agent 风格,如。

"User-Agent" = "UserAgentDemo/1 CFNetwork/1121.2.1 Darwin/19.2.0";
Run Code Online (Sandbox Code Playgroud)

我们可以自定义用户代理。

let config = URLSessionConfiguration.default
config.httpAdditionalHeaders = ["User-Agent": "zgpeace User-Agent"]
Run Code Online (Sandbox Code Playgroud)

我在下面为 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()

    }
Run Code Online (Sandbox Code Playgroud)

顺便说一句,WKWebView 中默认的 User-Agent 是不同的,比如

Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X)
Run Code Online (Sandbox Code Playgroud)

您可以自定义 WKWebView User-Agent

webView.customUserAgent = "zgpeace User-Agent"
Run Code Online (Sandbox Code Playgroud)

我还为 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"
        }
    }
Run Code Online (Sandbox Code Playgroud)

警告:当 webView 发布时,webView 中的“User-Agent”为零。您可以将 webView 对象设置为属性以保留 webView。

NSURLConnection 默认发送 User-Agent
默认的 User-Agent 风格,如。

"User-Agent" = "UserAgentDemo/1 CFNetwork/1121.2.1 Darwin/19.2.0";
Run Code Online (Sandbox Code Playgroud)

我们可以自定义用户代理。

urlRequest.setValue("URLConnection zgpeace User-Agent", forHTTPHeaderField: "User-Agent")
Run Code Online (Sandbox Code Playgroud)

我在下面为 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
    }

  }
Run Code Online (Sandbox Code Playgroud)

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


小智 5

是的,用户代理是作为默认会话配置的一部分自动提供的.

默认NSURLSession请求标头User-Agent字段包括watchOS应用程序扩展的Bundle Name(CFBundleName)和Build Number(CFBundleVersion):

$(CFBundleName)/$(CFBundleVersion) CFNetwork/808.3 Darwin/16.3.0
Run Code Online (Sandbox Code Playgroud)

请注意,您的应用版本号(CFBundleShortVersionString)不包括在内.(有关详细信息,请参阅技术说明TN2420:版本号和内部编号.)

例如,对于具有Build Number 1的产品"Foo",您的用户代理将是:

Foo%20WatchKit%20Extension/1 CFNetwork/808.3 Darwin/16.3.0
Run Code Online (Sandbox Code Playgroud)

如何验证?

我不认为您的应用程序中有一种方法可以检查默认的用户代理字段,因为它是nil(除非您将其设置为自定义值).

但是,您可以使用netcat来检查模拟器发送的请求.

  1. nc -l 5678在终端中运行以使netcat侦听发送到localhost端口的请求5678

  2. 在应用程序的Info.plist文件中,添加"允许任意负载"键设置为"应用程序传输安全设置"字典YES

  3. 将以下代码添加到开头 application(_:didFinishLaunchingWithOptions:)

    let url = URL(string: "http://localhost:5678/")!
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        let body = String(data: data!, encoding: .utf8)!
        print("body: \(body)")
    }.resume()
    return true
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在模拟器中运行您的应用程序,查看终端中的netcat输出

如果您的隐私无关紧要,可以使用user-agent.me等服务在您的设备上进行测试.

  1. 替换localhost:5678上面user-agent.me

  2. 在您的设备上运行您的应用

  3. 检查Xcode的控制台输出

完成验证后,请记住撤消上述所有更改.