從用戶輸入手機驗證碼開始

image

驗證用戶的有效性或者安全性,是每一個系統必備的安全措施,在移動端優先的時代,利用手機驗證碼來驗證用戶,算是安全係數比較高的手段。放眼當下幾乎全部的互聯網應用幾乎都開放了手機驗證碼登陸,並且應用內的敏感操做都須要手機驗證碼或者指紋,甚至面部識別來肯定當前操做人的權限。算法

拋開其餘端,單就移動端App方式而言,若是用戶頻繁進行敏感操做,須要頻繁發送驗證碼,其實在用戶體驗上並不友好,何況短信費用也隨之增長。就App形式而言,驗證一個用戶的有效性其實能夠演變爲驗證設備的有效性,即:當前人在當前設備上是否可信。設計模式

image

如下討論只針對非Web(瀏覽器)環境,Web環境其實也能夠根據瀏覽器的信息來生成一個相似設備標示的代碼

不少系統在設計之初,就已經考慮到安全主設備的概念,就像微信,若是在同一個手機上打開是不須要每次都進行登陸操做的。進行設備驗證是每一個安全系統比較重要的部分,推薦在系統設計之初就要考慮。迴歸正題,對於不少行業來講,用戶在App內頻繁進行一些敏感操做是很正常的,好比我所在的在線教育行業,老師會很頻繁的在一個班級內添加學生和老師(咱們認爲這些操做屬於敏感操做)。若是每次都須要老師發送驗證碼來進行操做,那交互上真的是太不友好。要想保證業務操做的安全性以及改善交互操做,咱們就須要抽象出問題的根本所在。瀏覽器

發送驗證碼操做最終的目的是爲了驗證操做人是操做人,聽起來很繞是否是。實現這個最終目的,其實有不少解決方案,其中用戶可信設備就屬於其中一類,而手機驗證碼方式又是用戶可信設備實現的一種方式,具體來講有幾點:安全

  1. 用戶利用手機驗證碼在這個設備上進行過敏感操做,就認爲這個設備在一段時間內是可信任的。
  2. 用戶在可信任的設備上進行其餘敏感操做,若是在有效期內,就能夠作到不發送驗證碼
  3. 用戶的敏感操做也能夠進行分級,最高敏感級必須輸入驗證碼才能夠進行操做(好比重置密碼,驗證碼登錄),通常敏感級在可信設備有效期內能夠不輸入驗證碼。

image

基於以上所說,系統設計的時候就能夠抽象出一個用戶可信設備中心,包括敏感操做的定義,可信設備的有效時長,可信設備的定義(好比:驗證碼經過的設備可定義爲有效設備)等等概念。經過這樣設計,短信驗證只不過成爲驗證用戶信任設備的一種途經,徹底能夠作到和具體業務無關(敏感級別最高操做除外),通常敏感的操做業務接口也能夠避免添加驗證碼參數,真正的把驗證和業務相分離,豈不美哉?微信

通過這樣抽象,用戶可信設備中心其實本質的接口只有幾個:數據結構

  1. 驗證設備是否有效
  2. 設置設備有效
  3. 設備有效的途經(例如短信驗證碼方式)

固然你的系統首先要有設備的概念,若是非要寫幾行代碼的話架構

  1. 驗證設備有效
public async Task<int> CheckUserDevice(UserDeviceReq para)
        {
            
            if (para == null || string.IsNullOrWhiteSpace(para.DeviceName) || para.UserId <= 0)
            {
                return 0;
            }
            //檢查簽名
            var sign = EncrypHelper.MD5Encrypt($"{SysConfig.SecretKey}_{para.UserId}_{para.DeviceName}");
            if (sign != para.Sign)
            {
                return 0;
            }
            string key = $"{para.UserId}_{para.DeviceName}";
            var authRet = await RedisClient.GetString(key);
            if (string.IsNullOrWhiteSpace(authRet))
            {
                //告訴客戶端須要短信驗證碼
                return 414000;
            }
            return 1;
        }
  1. 設置設備有效
public async Task<int> SetUserDevice(UserDeviceReq para)
        {
            
            if (para == null || string.IsNullOrWhiteSpace(para.DeviceName) || para.UserId <= 0)
            {
                return 0;
            }
            //檢查簽名
            var sign = EncrypHelper.MD5Encrypt($"{SysConfig.SecretKey}_{para.UserId}_{para.DeviceName}");
            if (sign != para.Sign)
            {
                return 0;
            }
            string key = $"{para.UserId}_{para.DeviceName}";
            var cacheRet = await RedisClient.GetString(key);
            if (string.IsNullOrWhiteSpace(cacheRet))
            {
                UserDeviceInfo value = new UserDeviceInfo() { UserId = para.UserId, DeviceName = para.DeviceName, OperationCode = para.OperationCode, CreateDate = DateTime.Now, Context = "" };
                var userDeviceExp = SysConfig.GetAppSetting("Config:UserDeviceExpire");
                if (string.IsNullOrWhiteSpace(userDeviceExp))
                {
                    userDeviceExp = "300";
                }
                var authRet = await RedisClient.SetString(key, JsonConvert.SerializeObject(value), TimeSpan.FromMinutes(int.Parse(userDeviceExp)));
                if (!authRet)
                {
                    return 0;
                }
            }
            return 1;
        }

更多精彩文章併發

image

相關文章
相關標籤/搜索