mPaas離線包之內網環境iOS客戶端白頁問題查看從入門到放棄

 

 

手機連不上內網已經解決了,

手機udid沒加也解決了。

 

不得不說mPaas把h5容器封裝的很死,即使完全知道本地h5如何在webview加載的,也很難查看其問題。

h5離線包只能加載從發佈平臺導出來的h5代碼,即使想改,自己也改不了,改了,也得在發佈平臺重新發布纔可以用。

如果是明文的h5自己就可以攔截替換一些文件,隨便加點代碼。

 

 

解決:修改h5代碼(加點彈窗),發佈h5代碼,可能需要很多次,查看哪行代碼沒有執行下去。在螞蟻的人不改客戶端的情形下。

 

 

混淆後的一個js文件有300k,900k,xcode打開都直接卡死。

下面是客戶端能看到的 混淆後的js小部分
2,0),a.maxY=-a.minY,a.touchesCurrent.x="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,a.touchesCurrent.y="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,!a.isMoved&&!i.isScaling){if(t.isHorizontal()&&(Math.floor(a.minX)===Math.floor(a.startX)&&a.touchesCurrent.x<a.touchesStart.x||Math.floor(a.maxX)===Math.floor(a.startX)&&a.touchesCurrent.x>a.touchesStart.x))return void(a.isTouched=!1);if(!t.isHorizontal()&&(Math.floor(a.minY)===Math.floor(a.startY)&&a.touchesCurrent.y<a.touchesStart.y||Math.floor(a.maxY)===Math.floor(a.startY)&&a.touchesCurrent.y>a.touchesStart.y))return void(a.isTouched=!1)}e.preventDefault(),e.stopPropagation(),a.isMoved=!0,a.currentX=a.touchesCurrent.x-a.touchesStart.x+a.startX,a.currentY=a.touchesCurrent.y-a.touchesStart.y+a.startY,a.currentX<a.minX&&(a.currentX=a.minX+1-Math.pow(a.minX-a.currentX+1,.8)),a.currentX>a.maxX&&(a.currentX=a.maxX-1+Math.pow(a.currentX-a.maxX+1,.8)),a.currentY<a.minY&&(a.currentY=a.minY+1-Math.pow(a.minY-a.currentY+1,.8)),a.currentY>a.maxY&&(a.currentY=a.maxY-1+Math.pow(a.currentY-a.maxY+1,.8)),n.prevPositionX||(n.prevPositionX=a.touchesCurrent.x),n.prevPositionY||(n.prevPositionY=a.touchesCurrent.y),n.prevTime||(n.prevTime=Date.now()),n.x=(a.touchesCurrent.x-n.prevPositionX)/(Date.now()-n.prevTime)/2,n.y=(a.touchesCurrent.y-n.prevPositionY)/(Date.now()-n.prevTime)/2,Math.abs(a.touchesCurrent.x-n.prevPositionX)<2&&(n.x=0),Math.abs(a.touchesCurrent.y-n.prevPositionY)<2&&(n.y=0),n.prevPositionX=a.touchesCurrent.x,n.prevPositionY=a.touchesCurrent.y,n.prevTime=Date.now(),s.$imageWrapEl.transform("translate3d("+a.currentX+"px, "+a.currentY+"px,0)")}}},onTouchEnd:function(){var e=this.zoom,t=e.gesture,i=e.image,s=e.velocity;if(t.$imageEl&&0!==t.$imageEl.length){if(!i.isTouched||!i.isMoved)return i.isTouched=!1,void(i.isMoved=!1);i.isTouched=!1,i.isMoved=!1;var a=300,n=300,r=s.x*a,o=i.currentX+r,l=s.y*n,d=i.currentY+l;0!==s.x&&(a=Math.abs((o-i.currentX)/s.x)),0!==s.y&&(n=Math.abs((d-i.currentY)/s.y));var c=Math.max(a,n);i.currentX=o,i.currentY=d;var p=i.width*e.scale,h=i.height*e.scale;i.minX=Math.min(t.slideWidth/2-p/2,0),i.maxX=-i.minX,i.minY=Math.min(t.slideHeight/2-h/2,0),i.maxY=-i.minY,i.currentX=Math.max(Math.min(i.currentX,i.maxX),i.minX),i.currentY=Math.max(Math.min(i.currentY,i.maxY),i.minY),t.$imageWrapEl.transition(c).transform("translate3d("+i.currentX+"px, "+i.currentY+"px,0)")}},onTransitionEnd:function(){var e=this.zoom,t=e.gesture;t.$slideEl&&this.previousIndex!==this.activeIndex&&(t.$imageEl.transform("translate3d(0,0,0) scale(1)"),t.$imageWrapEl.transform("translate3d(0,0,0)"),e.scale=1,e.currentScale=1,t.$slideEl=void 0,t.$imageEl=void 0,t.$imageWrapEl=void 0)},toggle:function(e){var t=this.zoom;t.scale&&1!==t.scale?t.out():t.in(e)},in:function(t){var i,s,a,n,r,o,l,d,c,p,h,u,v,m,f,g,y=this,w=y.zoom,b=y.params.zoom,C=w.gesture,S=w.image;C.$slideEl||(C.$slideEl=y.clickedSlide?e(y.clickedSlide):y.slides.eq(y.activeIndex),C.$imageEl=C.$slideEl.find("img, svg, canvas"),C.$imageWrapEl=C.$imageEl.parent("."+b.containerClass)),C.$imageEl&&0!==C.$imageEl.length&&(C.$slideEl.addClass(""+b.zoomedSlideClass),void 0===S.touchesStart.x&&t?(i="touchend"===t.type?t.changedTouches[0].pageX:t.pageX,s="touchend"===t.type?t.changedTouches[0].pageY:t.pageY):(i=S.touchesStart.x,s=S.touchesStart.y),w.scale=C.$imageWrapEl.attr("data-swiper-zoom")||b.maxRatio,w.currentScale=C.$imageWrapEl.attr("data-swiper-zoom")||b.maxRatio,t?(f=C.$slideEl[0].offsetWidth,g=C.$slideEl[0].offsetHeight,a=C.$slideEl.offset().le

 

客戶端調用方法有限。

通過控制檯的打印:在加載h5包時會有一些日誌打印發現了兩點

 

1.行爲分析的外網js,通過MyConnectionURLProtocol攔截到外網的js鏈接地址,然後從整個工程掃描這個地址,發現是行爲分析的framework裏面的。

把他關掉:NBLogConfigurationGet().shouldInjectSPMJS = NO;


2.長鏈接:通過c語言hook系統日誌打印方法nslog發現有幾個日誌是[DTLongLinkDataDispatch cmdTimeout:]打印出來的。

然後把他也關掉    [MySyncService sharedInstance]這個方法註釋掉。

 

再然後控制檯沒有什麼有用信息了。

 

開始的時候又寫了一個MyConnectionURLProtocol。想攔截處理,但是螞蟻內部已經有了一個PSDWebViewURLProtocol,這樣兩個都會走。那就把PSDWebViewURLProtocol的方法都hook過來吧

//
//  PSDWebViewURLProtocol+YYY.h
//  
//
//  Created by YYY on 2019/9/10.
//  Copyright © 2019 Alibaba. All rights reserved.
//



NS_ASSUME_NONNULL_BEGIN
@interface PSDWebViewURLProtocol:NSURLProtocol
@end

@interface PSDWebViewURLProtocol (YYY)

@end

NS_ASSUME_NONNULL_END
//
//  PSDWebViewURLProtocol+YYY.m
//
//
//  Created by YYY on 2019/9/10.
//  Copyright © 2019 Alibaba. All rights reserved.
//

#import "PSDWebViewURLProtocol+YYY.h"

@interface PSDWebViewURLProtocol () <NSURLConnectionDataDelegate>

@property (nonatomic, strong) NSURLConnection * connection;
@property (nonatomic, assign) NSStringEncoding stringEncoding ;
@end

@implementation PSDWebViewURLProtocol (YYY)
+ (void)load
{
    {
        Method originalMethod = class_getClassMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(canInitWithRequest:));
        
        Method swizzledMethod = class_getClassMethod([self class], @selector(canInitWithRequestS:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    {
        Method originalMethod = class_getClassMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(canonicalRequestForRequest:));
        
        Method swizzledMethod = class_getClassMethod([self class], @selector(canonicalRequestForRequestS:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    {
        Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(startLoading));
        
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(stopLoadingS));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    {
        Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(connection:didReceiveResponse:));
        
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(connection:didReceiveResponseS:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    {
        Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(connection:didReceiveData:));
        
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(connection:didReceiveDataS:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    {
        Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(connectionDidFinishLoading:));
        
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(connectionDidFinishLoadingS:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    {
        Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(connection:didFailWithError:));
        
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(connection:didFailWithErrorS:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    //
    //
    //
    //
}

+ (BOOL)canInitWithRequestS:(NSMutableURLRequest *)request {
    
    NSMutableURLRequest *mutableReq = [request mutableCopy];
    NSMutableDictionary *headers = [mutableReq.allHTTPHeaderFields mutableCopy];
    if ([headers[@"Key1"]  isEqualToString:@"AAAA" ]){
        return NO;
    }  
    
    if([request .URL.description hasPrefix:@"http://"]){
//        return YES;
    }
    
    NSLog(@"PSDWebViewURLProtocol canInitWithRequestS %@" ,request);;
    return [self canInitWithRequestS:request];
}
//
//修改請求頭 防止死循環
//
+ (NSURLRequest *)canonicalRequestForRequestS:(NSURLRequest *)request {
    
    if([request .URL.description hasPrefix:@"http://"]){
        // 修改了請求的頭部信息
        NSMutableURLRequest *mutableRequest = [request mutableCopy];
        [mutableRequest setValue:@"AAAA" forHTTPHeaderField:@"Key1"];
        
        if ([mutableRequest allHTTPHeaderFields].count < 1) {
            NSLog(@"空的空的");
        }
        NSLog(@"connection reset header");
        return mutableRequest;
        return request;
    }else{
        return [self canonicalRequestForRequestS:request];

    }
    

}

//
//開始加載
//
- (void)startLoadingS{
    
    
    NSMutableURLRequest *request = [self.request mutableCopy];

    if([request .URL.description hasPrefix:@"http://"]){

        self.connection = [NSURLConnection connectionWithRequest:request delegate:self];

    }else{
         [self startLoadingS];

    }
    
//替換爲本地文件使用下面方法
//    if ([request.URL.absoluteString containsString:@"hhhh"]) {
//        NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:[[self request] URL]
//                                                              statusCode:200
//                                                             HTTPVersion:@"1.1"
//                                                            headerFields:nil];
//        //
//        //如果是需要更改的頁面則直接把數據返回給它 這個文件裏的代碼是通過第一次打印複製出來更改後的
//        //
//        NSString *myStr = [[NSBundle mainBundle]pathForResource:@"20190730_0.0.0.2" ofType:@"amr" inDirectory:nil];
//        NSData *localdata = [[NSData alloc]initWithContentsOfFile:myStr];
//        [[self client] URLProtocol:self
//                didReceiveResponse:response
//                cacheStoragePolicy:NSURLCacheStorageNotAllowed];
//        [[self client] URLProtocol:self didLoadData:localdata];
//        [[self client] URLProtocolDidFinishLoading:self];
//    }

}

//
//取消請求
//
- (void)stopLoadingS {
    
     [self stopLoadingS];
    
    
//    [self.connection cancel];
}

//
//#pragma mark - NSURLConnectionDelegate
//
- (void)connection:(NSURLConnection *)connection didReceiveResponseS:(NSURLResponse *)response {
    NSMutableURLRequest *request = [self.request mutableCopy];
    
    if([request .URL.description hasPrefix:@"http://"]){
        
        [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];

    }
      [self connection:connection didReceiveResponseS:response];
    
}
- (void)connection:(NSURLConnection *)connection didReceiveDataS:(NSData *)data {
    
    NSMutableURLRequest *request = [self.request mutableCopy];

    if([request .URL.description hasPrefix:@"http://"]){
        NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];;
        if (str.length < 1) {
            CFStringEncoding gbkEncoding =(unsigned int) CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
            
            str =[[NSString alloc]initWithData:data encoding:gbkEncoding];
        }
        //
        //打印h5的代碼
        //
        NSLog(@"%@ %@",connection,str);
        [self.client URLProtocol:self didLoadData:data];
        
    }else{
        return [self connection:connection didReceiveDataS:data];

    }
    

    

}
- (void)connectionDidFinishLoadingS:(NSURLConnection *)connection {
    NSMutableURLRequest *request = [self.request mutableCopy];
    
    if([request .URL.description hasPrefix:@"http://"]){
        [self.client URLProtocolDidFinishLoading:self];
    }else{
        [self connectionDidFinishLoadingS:connection];

    }
    
//
}
- (void)connection:(NSURLConnection *)connection didFailWithErrorS:(NSError *)error {
    
    NSMutableURLRequest *request = [self.request mutableCopy];
    
    if([request .URL.description hasPrefix:@"http://"]){
            [self.client URLProtocol:self didFailWithError:error];

    }else{
    [self connection:connection didFailWithErrorS:error];
    }
}

@end

 

這些代碼添加後能夠走進來,對A功能的h5離線包也能正常打開。

但是對於一直白屏的B功能,還是白屏,而且要找的那個http請求沒有走到這裏。看來只能使用上面的方法解決。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章