在個人混合式開發框架裏面,集成了WebAPI的訪問,這種訪問方式不只能夠實現簡便的數據交換,並且能夠在多種平臺上進行接入,如Winform程序、Web網站、移動端APP等多種接入方式,Web API的處理方式和微信提供的接口處理規則相似,也是經過向服務器得到訪問令牌(AccessToken),而後傳遞給每一個Web API接口,實現數據的交換處理。本篇隨筆主要介紹混合框架中Winform對Web API訪問的處理。html
《混合式開發框架》混合了Web API接口訪問、WCF接口訪問,以及直接訪問數據庫三種方式的接入,以適應多種場景的應用,是基於門面層的一種接口實現處理和封裝。是一種彈性化很是好的框架應用,既可用於單機版軟件或者基於局域網內的應用軟件,也能夠用於分佈式技術的互聯網環境應用,是一種成熟穩定、安全高效的技術框架。數據庫
關於這個框架的詳細介紹,能夠查看個人隨筆《Winform混合式開發框架的特色總結》進行詳細瞭解。api
這裏主要關注Web API的接入方式,咱們知道,若是是通常的接口,若是公佈在互聯網上面,就會有不少接入的風險,所以須要對接口的調用進行檢查校驗,確保訪問令牌有效,並且對數據發生修改的,還須要對數據的加密簽名進行檢查,才能保證咱們的接口運行在較爲安全的環境中。瀏覽器
混合框架調用Web API接口的詳細過程,能夠經過《Web API應用架構在Winform混合框架中的應用(3)--Winfrom界面調用WebAPI的過程分解》、《Web API應用架構在Winform混合框架中的應用(1)》、《Web API接口設計經驗總結》進行了解。緩存
因爲咱們須要對接口訪問的身份進行覈實,所以通常要求咱們的接口都帶有一個token參數,用來對用戶身份進行識別,以下所示是Web API層的MVC控制器的接口定義。安全
[HttpGet] public UserInfo GetUserByName(string userName, string token) { //令牌檢查,不經過則拋出異常 CheckResult checkResult = CheckToken(token); return BLLFactory<User>.Instance.GetUserByName(userName); }
若是咱們在客戶端須要調用這個接口,那麼就須要傳入這個token參數,也就是說這個token令牌須要在調用任何接口前得到,這樣才能爲咱們後面的接口調用作好準備。服務器
而這個token的產生是很是重要的,須要嚴格頒發,所以須要對獲取這個token的方法的參數進行簽名校驗,以下面代碼是WebAPI接口對產生token的處理。微信
/// <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> [HttpGet] public TokenResult GetAccessToken(string username, string password, string signature, string timestamp, string nonce, string appid)
也就是須要傳入用戶名、密碼、加密簽名、時間戳、隨機數、應用接入ID等信息,從而構建出來一個訪問令牌,經過用戶名、密碼、加密簽名校驗等方式,能夠實現對訪問令牌(token)的嚴格頒發處理。架構
在客戶端調用全部Web API接口前,咱們須要先經過上面的Web API接口,獲取到該用戶的訪問令牌,爲了方便,咱們能夠在客戶端封裝一個函數,經過這個函數獲取到對應的訪問令牌,而後把它存儲在緩存裏面,方便各個模塊的接口訪問處理。app
/// <summary> /// 用戶獲取令牌的輔助類 /// </summary> public class AccessTokenHelper { private const string APPID = "APPID";//應用ID,由系統管理員分配 private const string APPSECRET = "APPSECRET";//應用祕鑰,,由系統管理員分配 private const string DEFAULT_API_URL = "http://localhost:9001/api/Auth/GetAccessToken";//默認調試的Web API獲取受權地址 /// <summary> /// 設置簽名參數。 /// 因爲Web API大多數的接口,都須要驗證用戶身份的訪問令牌(accesstoken),所以用戶在登錄的時候,須要使用這個步驟去獲取令牌信息,而後在繼續後續的接口操做。 /// 該接口用到的應用ID、應用祕鑰等參數,由系統管理員統一分配。 /// </summary> public static bool GetAccessToken(string username, string password) { bool result = false; //配置使用Web API模式,須要構建登錄token才能訪問 AppConfig config = new AppConfig(); string callerType = config.AppConfigGet("CallerType"); string apiUrl = config.AppConfigGet("AuthApiUrl"); apiUrl = string.IsNullOrEmpty(apiUrl) ? DEFAULT_API_URL : apiUrl; if (callerType.Equals("api", StringComparison.OrdinalIgnoreCase)) { //使用API方式,須要在緩存裏面設置特殊的信息 var url = apiUrl + SignatureHelper.GetSignatureUrl(APPID, APPSECRET); url += string.Format("&username={0}&password={1}", username, password); TokenResult tokenResult = JsonHelper<TokenResult>.ConvertJson(url); result = !string.IsNullOrEmpty(tokenResult.access_token); if (tokenResult == null) { var message = "獲取受權信息出錯,請檢查地址是否正確!"; MessageDxUtil.ShowError(message); } var SignatureInfo = new SignatureInfo() { appid = APPID, appsecret = APPSECRET, token = (tokenResult != null) ? tokenResult.access_token : null }; Cache.Instance.Add("SignatureInfo", SignatureInfo); } return result; }
有了這個輔助方法,咱們能夠在程序啓動後,用戶進行身份登陸的時候,先調用這個方法來獲取令牌。
string ip = NetworkUtil.GetLocalIP(); string macAddr = HardwareInfoHelper.GetMacAddress(); string loginName = this.txtLoginName.Text.Trim(); string password = this.txtPassword.Text; //若是沒法獲取訪問令牌,則返回 bool hasGotToken = AccessTokenHelper.GetAccessToken(loginName, password); if (!hasGotToken) { return; }
剛纔我提到了Web API層的MVC控制器的接口定義,默認後面通常都有一個token參數,以下代碼所示
[HttpGet] public UserInfo GetUserByName(string userName, string token) { //令牌檢查,不經過則拋出異常 CheckResult checkResult = CheckToken(token); return BLLFactory<User>.Instance.GetUserByName(userName); }
而咱們爲了方便客戶端調用,通常在客戶端調用Web API的時候進行簡化了一下,把token參數拿掉,它的值從緩存裏面提取。如客戶端調用的封裝代碼以下所示。
public UserInfo GetUserByName(string userName) { var action = "GetUserByName"; string url = GetTokenUrl(action) + string.Format("&userName={0}", userName); UserInfo result = JsonHelper<UserInfo>.ConvertJson(url); return result; }
其中GetTokenUrl就是咱們根據token和方法名稱,構建一個鏈接字符串,函數實現以下所示。
/// <summary> /// 獲取單純包含token參數的鏈接 /// </summary> /// <param name="action">控制器方法名稱</param> /// <returns></returns> protected string GetTokenUrl(string action) { string url = ""; if (this.SignatureInfo != null) { var append = string.Format("?token={0}", SignatureInfo.token); string baseUrl = GetBaseUrl(); url = CombindUrl(baseUrl, action + append);//組合爲完整的訪問地址 } else { throw new ArgumentNullException("沒有在緩存裏面設置SignatureInfo簽名信息"); } return url; }
這樣最終咱們能夠得到相似下面的鏈接地址:
http://localhost:27206/api/Account/GetAccountTypeList?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxIiwiaWF0IjoxNDYzNTU3OTAzLCJqdGkiOiI3OGMyOGRhNC01ZjRjLTQxYzItOThkNC1lYmFkZTM3YjA4NjUiLCJuYW1lIjoiYWRtaW4iLCJjaGFubmVsIjoiMCIsInNoYXJlZGtleSI6IjEyMzRhYmNkIn0.DysdbGx70xuIxXBz3G3x3MkGh9ZxL2zF9Fzu8FGVS0w
有了這個令牌組裝好的URL,咱們能夠對訪問結果的JSON字符串進行解析,把它解析爲對應的數據就能夠了。
固然,在實際的Web API接口開發過程當中,咱們還可使用Web API工具進行接口調試,以下所示。
下面的1-5的標識就是獲取token所須要的簽名數據,固然鏈接還帶有幾個帳號認證所須要的信息了,如帳號密碼、所在公司等信息。
固然咱們也可使用瀏覽器進行測試獲取Token的信息,只是沒有那麼方便而已。