如何获取WebView中每个请求的服务器响应代码

Bog*_*hin 4 objective-c webview ios

我有通过 WebView 管理的授权逻辑:

  • 用户点击应用中的登录按钮
  • 我打开 WebView 加载登录网页(通过 url 地址打开)
  • 用户提供他们的登录名和密码 > 点击页面上的登录按钮
  • 在WebView中打开下一页-授权访问确认页面
  • 用户必须点击网页上的授权访问按钮
  • 在此 redirect_uri URL 将尝试在 WebView 中打开之后
  • 我在请求中捕获了这个 redirect_uri 并关闭了 WebView

我检查了 WebView 委托方法中的所有请求(为了捕获 redirect_uri)shouldStartLoadWithRequest:

问题:如何为在 WebView 中打开的页面的每个请求管理服务器响应?

关键是我们的身份验证服务器存在一些问题,并且它不时显示错误页面。所以我想捕捉这样的页面并在这种情况下关闭 WebView。

Bog*_*hin 6

通过 找到了解决方案WKWebView。我以与UIWebView在我的项目中工作的方式相同的方式连接它。

然后我实际上使用了WKNavigationDelegate协议中的两种方法:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
Run Code Online (Sandbox Code Playgroud)

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
Run Code Online (Sandbox Code Playgroud)

代码示例:

第一种方法是检查当前请求是否实际上redirect_uri是我们应该处理的:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSLog(@"request: %@", navigationAction.request);

    // check whether this request should be stopped - if this is redirect_uri (like user is already authorized)
    if (...) {
        self.webView.navigationDelegate = nil;

        // do what is needed to send authorization data back
        self.completionBlock(...);

        // close current view controller
        [self dismissViewControllerAnimated:YES completion:nil];

        // stop executing current request
        decisionHandler(WKNavigationActionPolicyCancel);

    } else {
        // otherwise allow current request
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}
Run Code Online (Sandbox Code Playgroud)

第二种方法是分析来自服务器的响应,在这里我们可以验证状态码以处理任何错误

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;

    // filter the responses, in order to verify only the response from specific domain
    if ([[NSString stringWithFormat:[[response URL] absoluteString]] containsString:@"some.domain.com/"]) {

        NSInteger statusCode = [response statusCode];

        // check what is the status code
        if (statusCode == 200 ||
            statusCode == 301 ||
            statusCode == 302) {

            // allow response as everything is ok
            decisionHandler(WKNavigationResponsePolicyAllow);

        } else {
            // handle the error (e.g. any of 4xx or any others)

            self.webView.navigationDelegate = nil;

            // send needed info back
            self.completionBlock(...);

            // close current view controller
            [self dismissViewControllerAnimated:YES completion:nil];

            // stop current response
            decisionHandler(WKNavigationResponsePolicyCancel);
        }

    } else {
        // current response is not from our domain, so allow it
        decisionHandler(WKNavigationResponsePolicyAllow);
    }
}
Run Code Online (Sandbox Code Playgroud)