你好,歡迎來到IOS教程網

 Ios教程網 >> IOS訊息 >> 關於IOS >> Web API應用架構設計分析

Web API應用架構設計分析

編輯:關於IOS

在上篇隨筆《Web API應用架構設計分析(1)》,我對Web API的各種應用架構進行了概括性的分析和設計,Web API 是一種應用接口框架,它能夠構建HTTP服務以支撐更廣泛的客戶端(包括浏覽器,手機和平板電腦等移動設備)的框架,本篇繼續這個主題,介紹如何利用ASP.NET Web API 來設計Web API層以及相關的調用處理。

1、Web API的接口訪問分類

Web API接口的訪問方式,大概可以分為幾類:

1)一個是使用用戶令牌,通過Web API接口進行數據訪問。這種方式,可以有效識別用戶的身份,為用戶接口返回用戶相關的數據,如包括用戶信息維護、密碼修改、或者用戶聯系人等與用戶身份相關的數據。

2)一種是使用安全簽名進行數據提交。這種方式提交的數據,URL連接的簽名參數是經過安全一定規則的加密的,服務器收到數據後也經過同樣規則的安全加密,確認數據沒有被中途篡改後,再進行數據修改處理。因此我們可以為不同接入方式,如Web/APP/Winfrom等不同接入方式指定不同的加密秘鑰,但是秘鑰是雙方約定的,並不在網絡連接上傳輸,連接傳輸的一般是這個接入的AppID,服務器通過這個AppID來進行簽名參數的加密對比,這種方式,類似微信後台的回調處理機制,它們就是經過這樣的處理。

3)一種方式是提供公開的接口調用,不需要傳入用戶令牌、或者對參數進行加密簽名的,這種接口一般較少,只是提供一些很常規的數據顯示而已。

下面圖示就是這幾種接入方式的說明和大概應用場景。

Web API應用架構設計分析

 

2、Web API使用安全簽名的實現

首先我們為用戶注冊的時候,需要由我們認可的終端發起,也就是它們需要進行安全簽名,後台確認簽名有效性,才能正常實現用戶注冊,否則遭到偽造數據,系統就失去原有的意義了。







/// <summary>
/// 注冊用戶信息接口
/// </summary>
public interface IUserApi
{
/// <summary>
/// 注冊用戶處理,包括用戶名,密碼,身份證號,手機等信息
/// </summary>
/// <param name="json">注冊用戶信息</param>
/// <param name="signature">加密簽名字符串</param>
/// <param name="timestamp">時間戳</param>
/// <param name="nonce">隨機數</param>
/// <param name="appid">應用接入ID</param>
/// <returns></returns>
ResultData Add(UserJson json,
string signature, string timestamp, string nonce, string appid);
}
其實我們獲得用戶的令牌,也是需要進行用戶安全簽名認證的,這樣我們才有效保證用戶身份令牌獲取的合法性。

/// <summary>
/// 系統認證等基礎接口
/// </summary>
public interface IAuthApi
{
/// <summary>
/// 注冊用戶獲取訪問令牌接口
/// </summary>
/// <param name="username">用戶登錄名稱</param>
/// <param name="password">用戶密碼</param>
/// <param name="signature">加密簽名字符串</param>
/// <param name="timestamp">時間戳</param>
/// <param name="nonce">隨機數</param>
/// <param name="appid">應用接入ID</param>
/// <returns></returns>
TokenResult GetAccessToken(string username, string password,
string signature, string timestamp, string nonce, string appid);
}
上面介紹到的參數,我們提及了幾個參數,一個是加密簽名字符串,一個是時間戳,一個是隨機數,一個是應用接入ID,我們一般的處理規則如下所示。

1)Web API 為各種應用接入,如APP、Web、Winform等接入端分配應用AppID以及通信密鑰AppSecret,雙方各自存儲。
2)接入端在請求Web API接口時需攜帶以下參數:signature、 timestamp、nonce、appid,簽名是根據幾個參數和加密秘鑰生成。
3) Web API 收到接口調用請求時需先檢查傳遞的簽名是否合法,驗證後才調用相關接口。

加密簽名在服務端(Web API端)的驗證流程參考微信的接口的處理方式,處理邏輯如下所示。

1)檢查timestamp 與系統時間是否相差在合理時間內,如10分鐘。
2)將appSecret、timestamp、nonce三個參數進行字典序排序
3)將三個參數字符串拼接成一個字符串進行SHA1加密
4)加密後的字符串可與signature對比,若匹配則標識該次請求來源於某應用端,請求是合法的。

C#端代碼校驗如下所示。

/// <summary>
/// 檢查應用接入的數據完整性
/// </summary>
/// <param name="signature">加密簽名內容</param>
/// <param name="timestamp">時間戳</param>
/// <param name="nonce">隨機字符串</param>
/// <param name="appid">應用接入Id</param>
/// <returns></returns>
public CheckResult ValidateSignature(string signature, string timestamp, string nonce, string appid)
{
CheckResult result = new CheckResult();
result.errmsg = "數據完整性檢查不通過";

//根據Appid獲取接入渠道的詳細信息
AppInfo channelInfo = BLLFactory<App>.Instance.FindByAppId(appid);
if (channelInfo != null)
{
#region 校驗簽名參數的來源是否正確
string[] ArrTmp = { channelInfo.AppSecret, timestamp, nonce };

Array.Sort(ArrTmp);
string tmpStr = string.Join("", ArrTmp);

tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
tmpStr = tmpStr.ToLower();

if (tmpStr == signature && ValidateUtil.IsNumber(timestamp))
{
DateTime dtTime = timestamp.ToInt32().IntToDateTime();
double minutes = DateTime.Now.Subtract(dtTime).TotalMinutes;
if (minutes > timspanExpiredMinutes)
{
result.errmsg = "簽名時間戳失效";
}
else
{
result.errmsg = "";
result.success = true;
result.channel = channelInfo.Channel;
}
}
#endregion
}
return result;
}

一旦我們完成對安全簽名進行成功認證,也就是我們對數據提交的來源和完整性進行了確認,就可以進行更多和安全性相關的操作了,如獲取用戶的訪問令牌信息的操作如下所示。

第一步是驗證用戶的簽名是否符合要求,符合要求後進行用戶信息的比對,並生成用戶訪問令牌數據JSON,返回給調用端即可。

Web API應用架構設計分析

 

3、Web API使用安全令牌的實現

通過上面的接口,我們獲取到的用戶訪問令牌,以後和用戶相關的信息調用,我們就可以通過這個令牌參數進行傳遞就可以了,這個令牌帶有用戶的一些基礎信息,如用戶ID,過期時間等等,這個Token的設計思路來源於JSON Web Token (JWT),具體可以參考http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html,以及GitHub上的項目https://github.com/jwt-dotnet/jwt。

由於Web API的調用,都是一種無狀態方式的調用方式,我們通過token來傳遞我們的用戶信息,這樣我們只需要驗證Token就可以了。

JWT的令牌生成邏輯如下所示

Web API應用架構設計分析

令牌生成後,我們需要在Web API調用處理前,對令牌進行校驗,確保令牌是正確有效的。

檢查的代碼,就是把令牌生成的過程逆反過來,獲取相應的信息,並且對令牌簽發的時間進行有效性判斷,一般可以約定一個失效時間,如1天或者7天,也不用設置太短。

  /// &lt;summary&gt;
 /// 檢查用戶的Token有效性
 /// &lt;/summary&gt;
 /// &lt;param name="token"&gt;&lt;/param&gt;
 /// &lt;returns&gt;&lt;/returns&gt;
 public CheckResult ValidateToken(string token)
 {
 //返回的結果對象
 CheckResult result = new CheckResult();
 result.errmsg = "令牌檢查不通過";

 if (!string.IsNullOrEmpty(token))
 {
 try
 {
 string decodedJwt = JsonWebToken.Decode(token, sharedKey);
 if (!string.IsNullOrEmpty(decodedJwt))
 {
 #region 檢查令牌對象內容
 dynamic root = JObject.Parse(decodedJwt);
 string username = root.name;
 string userid = root.iss;
 int jwtcreated = (int)root.iat;

 //檢查令牌的有效期,7天內有效
 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
 int timestamp = (int)t.TotalDays;
 if (timestamp - jwtcreated &gt; expiredDays)
 {
 throw new ArgumentException("用戶令牌失效.");
 }

 //成功校驗
 result.success = true;
 result.errmsg = "";
 result.userid = userid;
 #endregion
 }
 }
 catch (Exception ex)
 {
 LogTextHelper.Error(ex);
 }
 }
 return result;
 }
 
一般來說,訪問令牌不能永久有效,對於訪問令牌的重新更新問題,可以設置一個規則,只允許最新的令牌使用,並把它存儲在接口緩存裡面進行對比,應用系統退出的時候,就把內存裡面的Token移除就可以了。

4、ASP.NET Web API的開發

上面我們定義了一般的Web API接口,以及實現相應的業務實現,如果我們需要創建Web API層,還需要構建一個Web API項目的。

Web API應用架構設計分析

創建好相應的項目後,可以為項目添加一個Web API基類,方便控制共同的接口。

Web API應用架構設計分析

然後我們就可以在Controller目錄上創建更多的應用API控制器了。

Web API應用架構設計分析

最後我們為了統一所有的API接口都是返回JSON方式,我們需要對WebApiConfig裡面的代碼進行設置下。

  public static class WebApiConfig
 {
 public static void Register(HttpConfiguration config)
 {
 // Web API 配置和服務
 config.SetCorsPolicyProviderFactory(new CorsPolicyFactory());
 config.EnableCors();

 // Web API 路由
 config.MapHttpAttributeRoutes();

 config.Routes.MapHttpRoute(
 name: "DefaultApi",
 routeTemplate: "api/{controller}/{action}/{id}",
 defaults: new { action = "post", id = RouteParameter.Optional }
 );

 // Remove the JSON formatter
 //config.Formatters.Remove(config.Formatters.JsonFormatter);

 // Remove the XML formatter
 config.Formatters.Remove(config.Formatters.XmlFormatter);
 }
 }

5、Web API 接口的測試

接下來我們要做的就是需要增加業務接口,以便進行具體的測試了,建議使用Winform項目,對每個接口進行一個測試,或者也可以考慮使用單元測試的方式,看個人喜好吧。

例如我們如果要測試用戶登陸的接口的話,我們的測試代碼如下所示。

 

/// <summary>
/// 生成簽名字符串
/// </summary>
/// <param name="appSecret">接入秘鑰</param>
/// <param name="timestamp">時間戳</param>
/// <param name="nonce">隨機數</param>
private string SignatureString(string appSecret, string timestamp, string nonce)
{
string[] ArrTmp = { appSecret, timestamp, nonce };

Array.Sort(ArrTmp);
string tmpStr = string.Join("", ArrTmp);

tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
return tmpStr.ToLower();
}

private TokenResult GetTokenResult()
{
string timestamp = DateTime.Now.DateTimeToInt().ToString();
string nonce = new Random().NextDouble().ToString();
string signature = SignatureString(appSecret, timestamp, nonce);

string appended = string.Format("&signature={0}&timestamp={1}&nonce={2}&appid={3}", signature, timestamp, nonce, appId);
string queryUrl = url + "Auth/GetAccessToken?username=test&password=123456" + appended;

HttpHelper helper = new HttpHelper();
string token = helper.GetHtml(queryUrl);
Console.WriteLine(token);
TokenResult tokenResult = JsonConvert.DeserializeObject<TokenResult>(token);
return tokenResult;
}
如果我們已經獲得了令牌,我們根據令牌傳遞參數給連接,並獲取其他數據的測試處理代碼如下所示。

//獲取訪問令牌
TokenResult tokenResult = GetTokenResult();

string queryUrl = url + "/Contact/get?token=" + tokenResult.access_token;
HttpHelper helper = new HttpHelper();
string result = helper.GetHtml(queryUrl);
Console.WriteLine(result);
如果需要POST數據的話,那麼調用代碼如下所示。

//使用POST方式
var data = new
{
name = "張三",
certno = "123456789",
};
var postData = data.ToJson();

queryUrl = url + "/Contact/Add?token=" + tokenResult.access_token;
helper = new HttpHelper();
helper.ContentType = "application/json";
result = helper.GetHtml(queryUrl, postData, true);
Console.WriteLine(result);

   Web API後台,會自動把POST的JSON數據轉換為對應的對象的。

如果是GET方式,我們可能可以直接通過浏覽器進行調試,如果是POST方式,我們需要使用一些協助工具,如Fiddler等處理工具,但是最好的方式是自己根據需要弄一個測試工具,方便測試。

以下就是我為了自己Web API 接口開發的需要,專門弄的一個調試工具,可以自動組裝相關的參數,包括使用安全簽名的參數,還可以把所有參數數據進行存儲。

Web API應用架構設計分析

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved