Winform混合式開發框架訪問Web API接口的處理


在我的混合式開發框架里面,集成了WebAPI的訪問,這種訪問方式不僅可以實現簡便的數據交換,而且可以在多種平台上進行接入,如Winform程序、Web網站、移動端APP等多種接入方式,Web API的處理方式和微信提供的接口處理規則類似,也是通過向服務器獲得訪問令牌(AccessToken),然后傳遞給每個Web API接口,實現數據的交換處理。本篇隨筆主要介紹混合框架中Winform對Web API訪問的處理。

1、Web API接入方式介紹

《混合式開發框架》混合了Web API接口訪問、WCF接口訪問,以及直接訪問數據庫三種方式的接入,以適應多種場景的應用,是基於門面層的一種接口實現處理和封裝。是一種彈性化非常好的框架應用,既可用於單機版軟件或者基於局域網內的應用軟件,也可以用於分布式技術的互聯網環境應用,是一種成熟穩定、安全高效的技術框架。

關於這個框架的詳細介紹,可以查看我的隨筆《Winform混合式開發框架的特點總結》進行詳細了解。

這里主要關注Web API的接入方式,我們知道,如果是一般的接口,如果公布在互聯網上面,就會有很多接入的風險,因此需要對接口的調用進行檢查校驗,確保訪問令牌有效,而且對數據發生修改的,還需要對數據的加密簽名進行檢查,才能保證我們的接口運行在較為安全的環境中。

混合框架調用Web API接口的詳細過程,可以通過《Web API應用架構在Winform混合框架中的應用(3)--Winfrom界面調用WebAPI的過程分解》、《Web API應用架構在Winform混合框架中的應用(1)》、《Web API接口設計經驗總結》進行了解。

2、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接口,獲取到該用戶的訪問令牌,為了方便,我們可以在客戶端封裝一個函數,通過這個函數獲取到對應的訪問令牌,然后把它存儲在緩存里面,方便各個模塊的接口訪問處理。

    /// <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的信息,只是沒有那么方便而已。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM