Web API系列(二)介面安全和參數校驗

来源:http://www.cnblogs.com/wuzhe890919/archive/2017/04/28/6782186.html
-Advertisement-
Play Games

以前簡單介紹過web api 的設計,但是還是有很多朋友問我,如何合理的設計和實現web api。比如,介面安全,異常處理,統一數據返回等問題。所以有必要系統的總結總結 web api 的設計和實現。由於前面已經介紹過web api 的參數和返回格式的設計,《Web API系列(一)設計經驗與總結》 ...


  以前簡單介紹過web api 的設計,但是還是有很多朋友問我,如何合理的設計和實現web api。比如,介面安全,異常處理,統一數據返回等問題。所以有必要系統的總結總結 web api 的設計和實現。由於前面已經介紹過web api 的參數和返回格式的設計,《Web API系列(一)設計經驗與總結》這次,就來講講介面安全。

 

  由於Web API是基於互聯網的應用,因此安全性要遠比在本地訪問資料庫的要嚴格的多,一般通用的做法,是採用幾步來保證介面和數據安全:

  1.首先一個是基於CA證書的HTTPS進行數據傳輸,防止數據被竊聽;

  2.然後是採用參數加密簽名方式傳遞,對傳遞的參數,增加一個加密簽名,在伺服器端驗證簽名內容,防止被篡改;

  3.最後是對一般的介面訪問,都需要使用用戶身份的token進行校驗,只要檢查通過才允許訪問數據。

 

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

  1)使用用戶名密碼。這種方式比較簡單,可以有效識別用戶的身份(如包括用戶信息、密碼、或者相關的介面許可權等等)。驗證成功後,返回相關的數據。

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

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

   

 

  web api 安全校驗

  使用用戶名密碼的實現方式比較簡單,這裡就不說明如何實現了。就講一講安全簽名的實現。由於Web API的調用,都是一種無狀態的調用方式,所有的介面請求,都要帶安全簽名。

  

 

  web api核心安全校驗代碼片斷:

 public class QueryData
    {
        public QueryData()
        {

        }

        public QueryData(IEnumerable<KeyValuePair<string, string>> paramList)
        {
            // TODO: Complete member initialization
            try
            {
                if (paramList == null)
                {
                    throw new Exception("請求參數為空!");
                }

                foreach (var param in paramList)
                {
                    m_values[param.Key] = param.Value; //
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        //採用排序的Dictionary的好處是方便對數據包進行簽名,不用再簽名之前再做一次排序
        private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();

        /**
        * 設置某個欄位的值
        * @param key 欄位名
         * @param value 欄位值
        */
        public void SetValue(string key, object value)
        {
            m_values[key] = value;
        }

        /**
        * 根據欄位名獲取某個欄位的值
        * @param key 欄位名
         * @return key對應的欄位值
        */
        public object GetValue(string key)
        {
            object o = null;
            m_values.TryGetValue(key, out o);
            return o;
        }

        /**
         * 判斷某個欄位是否已設置
         * @param key 欄位名
         * @return 若欄位key已被設置,則返回true,否則返回false
         */
        public bool IsSet(string key)
        {
            object o = null;
            m_values.TryGetValue(key, out o);
            if (null != o)
                return true;
            else
                return false;
        }

        public string ToUrl()
        {
            string buff = "";
            foreach (KeyValuePair<string, object> pair in m_values)
            {
                if (pair.Value == null)
                {
                    throw new Exception("內部含有值為null的欄位!");
                }

                if (pair.Key != "sign" && pair.Value.ToString() != "")
                {
                    buff += pair.Key + "=" + pair.Value + "&";
                }
            }
            buff = buff.Trim('&');
            return buff;
        }

        public string MakeSign(string appKey = "test")
        {
            //轉url格式
            string str = ToUrl();
            //在string後加入API KEY
            str += "&key=" + appKey;
            //MD5加密
            var md5 = MD5.Create();
            var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
            var sb = new StringBuilder();
            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }
            //所有字元轉為大寫
            return sb.ToString().ToUpper();
        }
      

        public bool CheckSign()
        {
            //如果沒有設置簽名,則跳過檢測
            if (!IsSet("sign"))
            {
                throw new Exception("簽名存在但不合法!");
            }
            //如果設置了簽名但是簽名為空,則拋異常
            else if (GetValue("sign") == null || GetValue("sign").ToString() == "")
            {
                throw new Exception("簽名存在但不合法!");
            }

            //獲取接收到的簽名
            string return_sign = GetValue("sign").ToString();

            //在本地計算新的簽名
            string cal_sign = MakeSign();

            if (cal_sign == return_sign)
            {
                return true;
            }
            return false;
        }
    }

  代碼供大家參考和學習,正式的項目可以根據自己公司的需要去設計,後續也會開源相關的完整項目源代碼。

 

參考頁面:http://qingqingquege.cnblogs.com/p/5933752.html


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

-Advertisement-
Play Games
更多相關文章
  • 信號量: 是用來解決進程/線程之間的同步和互斥問題的一種通信機制,是用來保證兩個或多個關鍵代碼不被併發調用。 信號量(Saphore)由一個值和一個指針組成,指針指向等待該信號量的進程。信號量的值表示相應資源的使用情況。信號量S>=0時,S表示可用資源的數量。執行一次P操作意味著請求分配一個資源,因 ...
  • RedHat靜態Ip地址配置 依次修改以下三個文件: /etc/sysconfig/network /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/resolv.conf 1./etc/sysconfig/network NETWORKING=yes N ...
  • samba服務的安裝及配置:可以在Linux中建議共用目錄給網路中的其他主機 一、安裝: sudo apt-get install samba 二、配置: 1、創建一個需要共用的目錄,並修改許可權: xx@ubuntu:~$ mkdir linux-tq2440 xx@ubuntu:~$ sudo c ...
  • 在這裡對nginx的安裝簡單的做個記錄,後續有時間的話在詳細補充。 1.yum安裝gcc gcc-c++: 2.下載必需的依賴庫:zlib 、openssl 、pcre 3.安裝依賴庫:zlib 、openssl 、pcre 4.修改配置: 添加以下內容,註意位置: 5.測試配置問是否正確: 出現以 ...
  • 1 系統調用的作用 系統調用是操作系統提供給用戶(應用程式)的一組介面,每個系統調用都有一個對應的系統調用函數來完成相應的工作。用戶通過這個介面向操作系統申請服務,如訪問硬體,管理進程等等。 應用程式和文件系統的介面是系統調用。 我們經常看到的比如fork、open、write 等等函數實際上並不是 ...
  • 首先,來查看下系統當前都開放了什麼埠,怎樣查看呢?調出cmd命令行程式,輸入命令”netstat -na“,可以看到。 接著,可以發現當前系統開放了135、445以及5357埠,而且從狀態看都處於監聽狀態”Listening“。 然後,確認自己的系統已經開放了445埠之後,我們開始著手關閉這個 ...
  • 1 安裝tftp-server sudo apt-get install tftpd-hpa sudo apt-get install tftp-hpa(如果不需要客戶端可以不安裝) 2 配置tftp伺服器 第1步: 修改/etc/default/tftpd-hpa配置文件。 將/etc/defau ...
  • 最近有在學習會話共用的配置,其中一種呢是 nginx+redis+tomcat 的會話共用配置,在記錄此會話共用配置之前呢先記錄下redis等的安裝。這篇先簡單記錄下redis的安裝,是其中一種方式,其他的後續會進行補充或單獨記錄。 準備: 解壓tcl.tar.gz,並編譯安裝: 解壓redis.t ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...