博客園官方API--花樣作死封裝網路層(iOS或OSX)

来源:http://www.cnblogs.com/Erma-king/archive/2016/03/10/5262515.html
-Advertisement-
Play Games

博客園官方API 花樣作死封裝網路層(iOS或OSX) === 前一段時間通過孤獨的貓咪神瞭解到博客園有官方API,據說今年四月份下旬的樣子推出吧。(道聽途說!)...我小小的申請去測試了下,打算也用博客園官方的API寫一點兒東西,例如OSX和iOS的小軟體。。在之前博客園官方的API也是公開的,舊


博客園官方API--花樣作死封裝網路層(iOS或OSX)

前一段時間通過孤獨的貓咪神瞭解到博客園有官方API,據說今年四月份下旬的樣子推出吧。(道聽途說!)...我小小的申請去測試了下,打算也用博客園官方的API寫一點兒東西,例如OSX和iOS的小軟體。。在之前博客園官方的API也是公開的,舊的一套,HTTP的,返回的數據是XML,在iOS端下SAX解析有點麻煩。。。有點兒影響性能。。。


博客園官方API是HTTPS請求的,我在iOS下用AFN和NSURLSession花樣作死實現了網路層,哈哈本來標題是這麼長的,想想太長了,改改,文章寫了很久,內容不多,主要是研究AFN請求博客園的介面的時候費了點兒時間,而且最近也有點忙,,,都是晚上回家再研究的。。。HTTPS,證書可能是非CA或自簽名或伺服器HTTPS版本為1.1,反正只要是有這幾點,不管是博客園官方的API還是任何這樣的介面,首先都先設置一下ATS吧,再看這篇文章下麵的實現吧。。。 在iOS端用AFN有點兒麻煩,相反用蘋果自帶的NSURLSession實現起來還挺簡單的,因為有個代理和伺服器挑戰的功能,下麵會貼上代碼(~博客園給我的秘鑰隱藏了,遵守規定,保守秘密,dudu也看不到。。。哈哈~~)。


申請了開發者許可權後會給一個賬號和密碼,然後得算出AccessToken,下麵就說這三個事兒吧,第一個是算出AccessToken,第二個說說用NSURLSession寫網路層,第三個用AFN實現網路層,我相信很多朋友都在找AFN實現HTTPS請求的代碼吧,我就找過,網上真不是很多。。。因為蘋果官方的NSURLSession處理這樣的情況真的很好用!

一、算出AccessToken

演算法直接看dudu的文章吧,下麵是我用C實現的演算法。。。

static int base64_decode_map[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0   - 15
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16  - 31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32  - 47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48  - 63
-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, // 64  - 79
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80  - 95
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96  - 111
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112 - 127
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128 - 143
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144 - 159
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160 - 175
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176 - 191
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192 - 207
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208 - 223
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224 - 239
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 240 - 255
};

char *base64_decode(const char* input, char *output)
{
output[0] = '\0';
if (input == NULL || output == NULL)
    return output;

int input_len = (int)strlen(input);
if (input_len < 4 || input_len % 4 != 0)
    return output;

// 0xFC -> 11111100
// 0x03 -> 00000011
// 0xF0 -> 11110000
// 0x0F -> 00001111
// 0xC0 -> 11000000
char *p = (char*)input;
char *p_out = output;
char *p_end = (char*)input + input_len;
for (; p < p_end; p += 4) {
    *p_out++ = ((base64_decode_map[p[0]] << 2) & 0xFC) | ((base64_decode_map[p[1]] >> 4) & 0x03);
    *p_out++ = ((base64_decode_map[p[1]] << 4) & 0xF0) | ((base64_decode_map[p[2]] >> 2) & 0x0F);
    *p_out++ = ((base64_decode_map[p[2]] << 6) & 0xC0) | (base64_decode_map[p[3]]);
}

if (*(input + input_len - 2) == '=') {
    *(p_out - 2) = '\0';
} else if (*(input + input_len - 1) == '=') {
    *(p_out - 1) = '\0';
}

return output;
}

int main(int argc, const char * argv[]) {

char AccessToken[150];
strcpy (AccessToken,"Your ClientId");
strcat (AccessToken,":");
strcat (AccessToken,"Your ClientSercret");

int num[150];
for(int i=0;i<strlen(AccessToken);i++) num[i]=AccessToken[i];
for (int i = 0; i < strlen(AccessToken); i++) printf("%d",num[i]);

char decode[200];
char *input;
base64_decode(num, decode);
printf("%s",decode);

return 0;
}

演算法在dudu的文章里都有,上面的代碼不做過多講解了,只是蛋疼寫寫擺了,因為在oc下兩句代碼實現上面的功能,並且AFN內部也封裝了這個演算法,下麵看看oc的一句代碼,AFN就就不貼上來了

NSString *authString = [[[NSString stringWithFormat:@"%@:%@",ClientId,ClientSercret] dataUsingEncoding:NSUTF8StringEncoding] base64Encoding];

二、NSURLSession實現網路層

- (NSURLSession *)session {
if (_session == nil) {
    
    
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSString *str = @"Basic 這裡填寫通過將clientid和clientSecret用冒號拼接起來,然後轉成ASCII碼,然後再BASE64加密,計算出authString";
    // 設置請求頭
    config.HTTPAdditionalHeaders = @{@"Authorization":str};
    _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
    
}
return _session;
}

- (void)viewDidLoad {
[super viewDidLoad];

//    ClientId
    NSString *ClientId = @"你的ClientId";

//    ClientSercret
     NSString *ClientSercret = @"你的ClientSercret";

//     將clientid和clientSecret用冒號拼接起來,然後轉成ASCII碼,然後再BASE64加密,計算出authString
    NSString *authString = [[[NSString stringWithFormat:@"%@:%@",ClientId,ClientSercret] dataUsingEncoding:NSUTF8StringEncoding] base64Encoding];
    authString = [NSString stringWithFormat: @"Basic %@", authString];
//
NSLog(@"%@",authString);
NSURL *url = [NSURL URLWithString:@"你的API介面"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPBody = [@"你要攜帶的參數" dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPMethod = @"POST";

//    [request addValue:authString forHTTPHeaderField:@"Authorization"];

[[self.session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NSString *mJson = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
    NSLog(@"%@",mJson);
    NSLog(@"%@",response);
    NSLog(@"%@",error);
}] resume];

}

//挑戰伺服器。伺服器使用TLS1.0的協議,還需要開啟ATS
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
// 判斷認證方式(是用戶名密碼還是證書認證)
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
    // 設置信任伺服器的證書
    NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
    completionHandler(0,credential);
}
}

一些小小的tips

  • NSURLSessionConfiguration作用
    • 可以設置請求頭(Content-Type   Range User-Agent  Authorization等)
    • 可以設置最大連接數
    • 可以設置超時時長,緩存策略
    • 類方法,創建對象
  • defaultSessionConfiguration
    • 會使用磁碟緩存,賬戶信息存儲到鑰匙鏈,如果有cookie會攜帶cookie
    • ephemeralSessionConfiguration
    • 沒有磁碟緩存,不存儲賬戶信息,不攜帶cookie
    • 數據存儲在記憶體,速度快,如果要存儲到磁碟需要自己寫
  • backgroundSessionConfigurationWithIdentifier
    • 在一個單獨的進程上下載
    • app進入後臺或終止之後,依然可以繼續下載
  • 屬性
    • HTTPAdditionalHeaders:添加請求頭
    • requestCachePolicy:緩存策略
    • timeoutIntervalForRequest:請求的超時時長
    • allowsCellularAccess:運行蜂窩網路訪問
    • HTTPMaximumConnectionsPerHost:主機的最大連接數

搞iOS的朋友註意一下代理的方法

  • 接受伺服器的挑戰,信任伺服器

    • 發送請求之前先挑戰伺服器(進行HTTPS的協商)
    • https的協商
  1. 信任伺服器返回的證書(公鑰)
  2. 客戶端產生的隨機秘鑰
  3. 公鑰對 隨機秘鑰進行對稱加密(rsa)
  4. 把用公鑰加密的隨機秘鑰發送給伺服器
  5. 使用隨機秘鑰加密和伺服器交互

三、最後看看花樣作死用AFN實現,我還是建議用NSURLSession比較簡單

下麵貼出來的是網路層封裝的一個GET方法,其他的都一樣

+ (void)GET:(NSString *)urlString parameters:(id)parameters progress:(void(^)(NSProgress *downloadProgress))progress success:(void(^)(id responseObject))success failure:(void(^)(NSError *error))failure {

AFHTTPSessionManager *mgr =[AFHTTPSessionManager manager];
ERAuthorizationManager *authorMgr = [ERAuthorizationManager sharedERAuthorizationManager];
NSString *access_token =[NSString stringWithFormat:@"%@%@",@"Bearer ",[authorMgr getAccess_token]];
[mgr.requestSerializer setValue:access_token forHTTPHeaderField:@"Authorization"];
NSLog(@"%@",mgr.requestSerializer.HTTPRequestHeaders);

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
securityPolicy.allowInvalidCertificates = YES;
securityPolicy.validatesDomainName = NO;
[securityPolicy setValidatesDomainName:NO];
mgr.securityPolicy = securityPolicy;

[mgr GET:urlString parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
    
} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    if (success) {
        success(responseObject);
    }
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    if (failure) {
        failure(error);
        
    }
    
    NSLog(@"%ld",error.code);
}];    
}

下麵說說其中幾句關鍵代碼,並不複雜也不難,就是設置一下屬性就OK。

設置允許無效簽名證書(特別是這一步,十分重要呀!!!)

securityPolicy.allowInvalidCertificates = YES;

設置domain為no

securityPolicy.validatesDomainName = NO;

設置不需要驗證功能變數名稱

[securityPolicy setValidatesDomainName:NO];

好吧,其實沒有什麼難的地方,在網路層用AFN的時候查了查頭文件才知道一些屬性。。。因為不常用吧。。特別是AFN實現的HTTPS設置允許無效簽名證書的屬性。。

最後期待博客園官方的API能儘快上線吧,博客園重度用戶的期待。。。
最後,感謝孤獨的貓咪神對我細心的幫助,也感謝博客園。。。謝謝!!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、框架介紹 RequireJS 資料:http://www.requirejs.cn/RequireJS的目標是鼓勵代碼的模塊化,它使用了不同於傳統<script>標簽的腳本載入步驟。可以用它來加速 、優化代碼,但其主要目的還是為了代碼的模塊化。它鼓勵在使用腳本時以module ID替代URL地址
  • 依賴註入起源於實現控制反轉的典型框架Spring框架,用來削減電腦程式的耦合問題。簡單來說,在定義方法的時候,方法所依賴的對象就被隱性的註入到該方法中,在方法中可以直接使用,而不需要在執行該函數的時候再參數中添加這些依賴對象。 理解很簡單,我們以一個例子說明 var $name = "chua",
  • 其實要講的就只有一個,那就是給瀏覽器加上本地Ajax運行,當你使用到了某些angularJS的功能的時候,例如路由,你直接運行頁面打開之後你會發現是空白的,打開控制台 發現 XMLHttpRequest cannot load 這種字眼的時候,其實是告訴你瀏覽器禁止了本地的Ajax申請,你需要給瀏覽
  • 削減是一個從源代碼中刪除不必要的字元的技術使它看起來簡單而整潔。這種技術也被稱為代碼壓縮和最小化。在這裡,我們為你收集了10個最好的JavaScript壓縮工具將幫助您刪除不必要的空格,換行符,評論,等等。這樣,你將使你的源代碼,無雜波。削減你的源代碼將改善載入時間和Web應用的性能。 這裡是你的完
  • iew controllers 通常是 iOS 項目中最大的文件,並且它們包含了許多不必要的代碼。所以 View controllers 中的代碼幾乎總是復用率最低的。我們將會看到給 view controllers 瘦身的技術,讓代碼變得可以復用,以及把代碼移動到更合適的地方。 你可以在 Gith
  • TextView 是個非常有用的組件,可使用XML來定義,也可使用程式代碼中的 Method方法來定義。 android:autoLink 設置是否當文本為URL鏈接/email/電話號碼/map時,文本顯示為可點擊的鏈接。可選值(none/web/email/phone/map/all) andr
  • 可能是由於粘貼網頁上的代碼的時候兩行之間的回車引起的,兩行之間重新輸入回車就行...。。。刪掉重新寫一遍就ok了
  • 個人筆記與總結。
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...