最新消息:20190529 VPS服务器已从腾讯云香港换为Vultr新加坡,主题仍用朋友推荐的大前端D8

【部分解决】iOS的UIWebView手动设置Http请求的User-Agent

HTTP crifan 964浏览 0评论

项目特殊需求,需要在OC的iOS项目中的http网络请求报表中,手动加上对应的user-agent

之前代码是:

        let url = NSURL(string: RURL + “src/report/charts.html”);
        self.jsContext.evaluateScript(try? String(contentsOf: url! as URL, encoding: String.Encoding.utf8))

现在想要想办法去给js去加载的网页加上user-agent

ios oc jsContext.evaluateScript add header

JavaScriptCore by Example

JSContext – JavaScriptCore | Apple Developer Documentation

没找到可以加header的地方

ios – How to call JavaScript Function in objective C – Stack Overflow

感觉应该是去找webview,看看哪里可以加header

iOS中UIWebView与WKWebView、JavaScript与OC交互、Cookie管理看我就够(上)_IOS开发_互联网开发技术网_传播最新的编程技术_php361.com

ios oc UIWebView add header

ios – How to add customize HTTP headers in UIWebView request, my UIWebView is based on Cordova project? – Stack Overflow

objective c – iOS – How to add a custom header field to every request made by my UIWebView – Stack Overflow

objective c – UIWebView – shouldStartLoadWithRequest – NSMutableURLRequest – Stack Overflow

ios – How to set http header for all requests being loaded in a UIWebView? – Stack Overflow

ios uiwebview custom user agent

cocoa touch – Change User Agent in UIWebView (iPhone SDK) – Stack Overflow

ios – How can I set the “User-Agent” header of a UIWebView in Swift – Stack Overflow

去试试:

UserDefaults.standard.register(defaults: [“UserAgent”: “fle”])

问题依旧。

iOS中修改WebView默认的User Agent – 阿P的博客

iOS: 自定义 UIWebView 和 WKWebView 的 UserAgent | veryitman

用了:

//        let request = NSURLRequest(url: url! as URL)
        let request = NSMutableURLRequest(url: url! as URL)
//        request.setValue(“User-Agent”, forHTTPHeaderField: “fle”)
//        request.setValue(“UserAgent”, forHTTPHeaderField: “fle”)
        request.setValue(“fle”, forHTTPHeaderField: “User-Agent”)
        self.webView.loadRequest(request as URLRequest)

虽然实际上应该是生效了,但是最后在

    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool{

中得到的还是默认的user agent:

//        let reqUserAgent = request.value(forHTTPHeaderField: “UserAgent”)
        let reqUserAgent = request.value(forHTTPHeaderField: “User-Agent”)
        gLog.debug(“request.url=\(request.url), request.allHTTPHeaderFields=\(request.allHTTPHeaderFields),request.httpMethod=\(request.httpMethod),reqUserAgent=\(reqUserAgent)”)
        //request.allHTTPHeaderFields=Optional([“Accept”: “text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8”, “User-Agent”: “Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e”, “Upgrade-Insecure-Requests”: “1”]),request.httpMethod=Optional(“GET”),reqUserAgent=Optional(“Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e”)
        
        let appName = webView.stringByEvaluatingJavaScript(from: “navigator.appName”)
        let naviUserAgent = webView.stringByEvaluatingJavaScript(from: “navigator.userAgent”)
        gLog.debug(“appName=\(appName ?? “”), naviUserAgent=\(naviUserAgent ?? “”)”)
        //appName=Netscape, curUserAgent=Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e

而换上:

        UserDefaults.standard.register(defaults: [“UserAgent”: “fle”])
//        UserDefaults.standard.register(defaults: [“User-Agent”: “fle”])

倒的确可以获得user agent是fle了:

webView(_:shouldStartLoadWith:navigationType:) > request.url=Optional(http://x.x.x.x/skrDev/src/report/charts.html), request.allHTTPHeaderFields=Optional([“Accept”: “text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8”, “User-Agent”: “fle”, “Upgrade-Insecure-Requests”: “1”]),request.httpMethod=Optional(“GET”),reqUserAgent=Optional(“fle”)

但是最后在:

jsContext.evaluateScript执行url后,还是出错:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

相关代码:

    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool{
//        let reqUserAgent = request.value(forHTTPHeaderField: “UserAgent”)
        let reqUserAgent = request.value(forHTTPHeaderField: “User-Agent”)
        gLog.debug(“request.url=\(request.url), request.allHTTPHeaderFields=\(request.allHTTPHeaderFields),request.httpMethod=\(request.httpMethod),reqUserAgent=\(reqUserAgent)”)
        //request.allHTTPHeaderFields=Optional([“Accept”: “text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8”, “User-Agent”: “Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e”, “Upgrade-Insecure-Requests”: “1”]),request.httpMethod=Optional(“GET”),reqUserAgent=Optional(“Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e”)
        
        let appName = webView.stringByEvaluatingJavaScript(from: “navigator.appName”)
        let naviUserAgent = webView.stringByEvaluatingJavaScript(from: “navigator.userAgent”)
        gLog.debug(“appName=\(appName ?? “”), naviUserAgent=\(naviUserAgent ?? “”)”)
        //appName=Netscape, curUserAgent=Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e
        self.jsContext = webView.value(forKeyPath: “documentView.webView.mainFrame.javaScriptContext”) as! JSContext
        let model = AppHost()
        model.controller = self
        model.jsContext = self.jsContext
        // 这一步是将SwiftJavaScriptModel模型注入到JS中,在JS就可以通过WebViewJavascriptBridge调用我们暴露的方法了。
        self.jsContext.setObject(model, forKeyedSubscript: “AppHost” as (NSCopying & NSObjectProtocol)!)
        // 注册到网络Html页面 请设置允许Http请求
        //let url = “http://101.200.55.24/src/report/charts.html”;;
        let url = NSURL(string: RURL + “src/report/charts.html”);
        self.jsContext.evaluateScript(try? String(contentsOf: url! as URL, encoding: String.Encoding.utf8))
        return true
    }

所以此处问题变成:

如何在UIWebView,在为了和JS通讯,而用的documentView.webView.mainFrame.javaScriptContext的jsContext和evaluateScript中,传递对应的自定义的user-agent

即,希望在

self.jsContext.evaluateScript(try? String(contentsOf: url! as URL, encoding: String.Encoding.utf8))

之前,能想办法加上自定义的header

此处,也想要去直接在shouldStartLoadWith中设置webView.request,结果其是只读的,没法setValue。

ios javaScriptContext custom header

iOS下JS与原生OC互相调用(总结) – 简书

iOS中UIWebView与WKWebView、JavaScript与OC交互、Cookie管理看我就够(上) | Dark Angel

documentView.webView.mainFrame.javaScriptContext user-agent

UIWebView shouldStartLoadWith custom user-agent

ios – UIWebView User-Agent is not properly set for custom value – Stack Overflow

ios – Change User-Agent – Stack Overflow

UIWebView SwiftJavaScriptDelegate custom user-agent

UIWebView Swift JavaScript Delegate custom user-agent

ios – How can I set the “User-Agent” header of a UIWebView in Swift – Stack Overflow

现在问题是:

虽然给了webview设置了user-agent

但是当把documentView.webView.mainFrame.javaScriptContext设置给了JSContext后,

JSContext去通过evaluateScript执行url,打开url的,所以没了之前自定义的user-agent

所以此处需要去把JSContext的evaluateScrip中,添加自定义的user-agent

ios javaScriptContext custom user-agent

ios JSContext custom user-agent

iOS UIWebView 修改user-agent – 月若无涯的专栏 – CSDN博客

ios evaluateScript add user-agent

JSContext evaluateScript add user-agent

How to set user-agent in python-webkit – Stack Overflow

Objective-C/Swift与JavaScript交互 | 孟跃平的技术博客

JSContext open url add header

JSContext evaluateScript url add header

javascript – window.open with headers – Stack Overflow

JavaScriptCore 使用 – 简书

JSContext evaluateScript url

evaluateScript(_:) – JSContext | Apple Developer Documentation

evaluateScript(_:withSourceURL:) – JSContext | Apple Developer Documentation

iOS开发 – Swift使用JavaScriptCore与JS交互 – 马燕龙个人博客

JSContext evaluateScript withSourceURL

JSContext evaluateScript user-agent

JSContext evaluateScript change headers

试试:

self.jsContext.evaluateScript(“navigator.userAgent = \”fle\””)

不行。

iOS JSContext evaluateScript url

JavaScriptCore和Objective-C – 简书

去和服务器后台配合调试,发现iOS中通过:

self.jsContext.evaluateScript

去打开url时,默认的user-agent是:

“GET /skrDev/src/report/charts.html HTTP/1.1” 403 169 “-” “SRTDev/20170825 CFNetwork/811.4.18 Darwin/16.7.0” “-“

去搜:

UIWebView default user-agent

ios UIWebView default user-agent

ios UIWebView JSContext default user-agent

ios   JSContext default user-agent

但是还是找不到,当UIWebView中,通过JSContext的evaluateScript打开url时,默认的user-agent是什么。

算了。

【总结】

此处,Xcode9,swift 3中,可以通过:

1.去全局的设置固定的User-Agent的值:

UserDefaults.standard.register(defaults: [“UserAgent”: “fle”])

注意:key是UserAgent,而不是User-Agent

2.单个UIWebView的实例的User-Agent:

同时可以对于单个UIWebView的示例,可以通过:

        let request = NSMutableURLRequest(url: url! as URL)

        request.setValue(“fle”, forHTTPHeaderField: “User-Agent”)

        self.webView.loadRequest(request as URLRequest)

去设置User-Agent的值。

3.无法修改JSContext的evaluateScript打开的url时的User-Agent

但是对于:shouldStartLoadWith中的UIWebView获得的JSContext的evaluateScript去打开url的话:

则此处默认的User-Agent是

SRTDev/20170825 CFNetwork/811.4.18 Darwin/16.7.0

看起来是:

App 名称/时间  网络库名称/版本? 内核/版本?

而找不到办法,无法手动设置此时的User-Agent的。

【后记】

后来又遇到其他的问题:

在iOS模拟器中测试时,是可以正常访问后台的其他web页面的

但是在真机中测试,结果却无法正常访问内容了。

只能显示出异常的页面,无法获得内部用户数据,只有html页面内容。

看起来是:

缺少了token,所以获取不到用户的数据。

然后去让后台配合测试,发现真机中,(内部Webview去)访问其他web页面时,user-agent还是普通的apple的值,所以继续去改为:

给app初始化的部分就去全局添加

func resetGlobalValues(){
    gLog.info(“”)
    
    UserDefaults.standard.register(defaults: [“UserAgent”: APP_USER_AGENT])
}

然后后续的webview去访问(经过后台配置用fiddler抓包可以确认)user-agent都是希望的SRT了:

OPTIONS /v1/skr/report/daily/board HTTP/1.1Host: 123.206.101.36:9090Connection: keep-aliveAccept-Language: zh-cnAccess-Control-Request-Method: GETAccept-Encoding: gzip, deflateAccept: */*Origin: http://123.206.101.36Content-Length: 0Access-Control-Request-Headers: authorizationConnection: keep-aliveUser-Agent: SRTReferer: http://x.x.x.x/skrDev/src/report/charts.html

然后页面才能正常显示。

附上:

其他两种情况:

(1)iOS中用Alamofire网络库去调用api接口时:

User-Agent:是SRTDev/1.1.0 (com.csvw.fleDev; build:20171017; iOS 11.0.3) Alamofire/4.5.1

GET /v1/skr/task/common/organization?pid=SKR04-01-01 HTTP/1.1
Host: x.x.x.x:9090
Content-Type: application/json; charset=UTF-8
Connection: keep-alive
Connection: keep-alive
Accept: */*
User-Agent: SRTDev/1.1.0 (com.csvw.fleDev; build:20171017; iOS 11.0.3) Alamofire/4.5.1
Accept-Language: zh-Hans-CN;q=1.0, en-CN;q=0.9, zh-Hant-CN;q=0.8
Authorization: Bearer 662ijrcmmhfn9hmpnjjr4je34t
Accept-Encoding: gzip;q=1.0, compress;q=0.5

以及:

(2)webview中JSContext(调用evaluateScript)打开url时:

User-Agent是SRTDev/20171017 CFNetwork/887 Darwin/17.0.0

GET /skrDev/src/report/retail.html?t=1508231105061 HTTP/1.1
Host: 123.206.101.36
Connection: keep-alive
Accept: */*
User-Agent: SRTDev/20171017 CFNetwork/887 Darwin/17.0.0
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Connection: keep-alive

【后记2】

后来,为了配合后台改个bug:

后台的html页面是根据当前的user-agent判断是否是iPhone Plus机型而决定是否将报表显示高度减去顶部导航栏,

但是前面的做法,把正常的移动端的user-agent信息去掉了,(变成了”SRT”了)所以无法检测出iPhone机型了。

所以参考:

ios – How can I set the “User-Agent” header of a UIWebView in Swift – Stack Overflow

UIWebView 和 WKWebView 修改自定义UserAgent – Swift迷

再去改为:

在原有User-agent值的基础上,额外追加此处需要的”SRT”

func customAppUserAgent(){
    //    UserDefaults.standard.register(defaults: [“UserAgent”: APP_USER_AGENT])
    let webView = UIWebView(frame: CGRect.zero)
    let curUserAgent = webView.stringByEvaluatingJavaScript(from: “navigator.userAgent”)!
    //”Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e”
    UserDefaults.standard.register(defaults: [“UserAgent”: curUserAgent + ” \(APP_USER_AGENT)”])
    UserDefaults.standard.synchronize()
}

即可实现:

即可以识别user-agent中是否有特殊的我们此处自己定义的SRT

又可以保留之前已有的user-agent-》从而可以判断出iPhone的机型-》页面可以额外去做适配工作了。

转载请注明:在路上 » 【部分解决】iOS的UIWebView手动设置Http请求的User-Agent

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
66 queries in 0.102 seconds, using 18.88MB memory