asp.net core 騰訊驗證碼的接入

  • 2019 年 10 月 18 日
  • 筆記

asp.net core 騰訊驗證碼的接入

Intro

之前使用的驗證碼服務是用的極驗驗證,而且是比較舊的,好久之前接入的,而且驗證碼服務依賴 Session,有點不太靈活,後來發現騰訊也有驗證碼服務,而且支持小程序,並且是唯一支持小程序的驗證碼。。(壟斷么。。)

而且相比之下,騰訊驗證碼不需要依賴 Session,集成起來也比較方便,於是就用了騰訊驗證碼,詳細參考:https://007.qq.com/product.html?ADTAG=index.block

驗證流程

服務器端接入

using System.ComponentModel.DataAnnotations;  using System.Net.Http;  using System.Threading.Tasks;  using Microsoft.Extensions.Logging;  using Microsoft.Extensions.Options;  using Newtonsoft.Json;  using WeihanLi.Extensions;    namespace ActivityReservation.Common  {      public class TencentCaptchaOptions      {          /// <summary>          /// 客戶端AppId          /// </summary>          [Required]          public string AppId { get; set; }            /// <summary>          /// App Secret Key          /// </summary>          [Required]          public string AppSecret { get; set; }      }        public class TencentCaptchaRequest      {          /// <summary>          /// 驗證碼客戶端驗證回調的票據          /// </summary>          public string Ticket { get; set; }            /// <summary>          /// 驗證碼客戶端驗證回調的隨機串          /// </summary>          public string Nonce { get; set; }            /// <summary>          /// 提交驗證的用戶的IP地址(eg: 10.127.10.2)          /// </summary>          public string UserIP { get; set; }      }        public class TencentCaptchaHelper      {          private class TencentCaptchaResponse          {              /// <summary>              /// 1:驗證成功,0:驗證失敗,100:AppSecretKey參數校驗錯誤              /// </summary>              [JsonProperty("response")]              public int Code { get; set; }                /// <summary>              /// 惡意等級 [0, 100]              /// </summary>              [JsonProperty("evil_level")]              public string EvilLevel { get; set; }                /// <summary>              /// 錯誤信息              /// </summary>              [JsonProperty("err_msg")]              public string ErrorMsg { get; set; }          }            private const string TencentCaptchaVerifyUrl = "https://ssl.captcha.qq.com/ticket/verify";          private readonly TencentCaptchaOptions _captchaOptions;          private readonly ILogger _logger;          private readonly HttpClient _httpClient;            public TencentCaptchaHelper(              IOptions<TencentCaptchaOptions> option,              ILogger<TencentCaptchaHelper> logger,              HttpClient httpClient)          {              _captchaOptions = option.Value;              _logger = logger;              _httpClient = httpClient;          }            public async Task<bool> IsValidRequestAsync(TencentCaptchaRequest request)          {              // 參考文檔:https://007.qq.com/captcha/#/gettingStart              var response = await _httpClient.GetAsync(                  $"{TencentCaptchaVerifyUrl}?aid={_captchaOptions.AppId}&AppSecretKey={_captchaOptions.AppSecret}&Ticket={request.Ticket}&Randstr={request.Nonce}&UserIP={request.UserIP}");              var responseText = await response.Content.ReadAsStringAsync();              if (responseText.IsNotNullOrEmpty())              {                  _logger.Debug($"Tencent captcha verify response:{responseText}");                  var result = responseText.JsonToType<TencentCaptchaResponse>();                  if (result.Code == 1)                  {                      return true;                  }              }              return false;          }      }  }

Startup 配置:

services.AddHttpClient<TencentCaptchaHelper>(client => client.Timeout = TimeSpan.FromSeconds(3))      .ConfigurePrimaryHttpMessageHandler(() => new NoProxyHttpClientHandler());  services.AddTencentCaptchaHelper(options =>  {      options.AppId = Configuration["Tencent:Captcha:AppId"];      options.AppSecret = Configuration["Tencent:Captcha:AppSecret"];  });

前端接入

前端接入這裡不作多介紹了,接入方式多種多樣,具體可以參考官方文檔:https://cloud.tencent.com/document/product/1110/36841

下面的代碼是 angular spa 在前端接入的核心代碼

  private loadCaptcha(): void {      var tCaptcha = document.getElementById("tCaptcha");      if (tCaptcha) {        this.InitCaptcha();        return;      }      let script = <any>document.createElement('script');      script.id = "tCaptcha";      script.type = 'text/javascript';      script.src = "https://ssl.captcha.qq.com/TCaptcha.js"      if (script.readyState) {  //IE        script.onreadystatechange = () => {          if (script.readyState === "loaded" || script.readyState === "complete") {            this.InitCaptcha();          }        };      } else {  //Others        script.onload = () => {          this.InitCaptcha();        };      }      document.getElementsByTagName('body')[0].appendChild(script);    }      private InitCaptcha(): void {      let captchaDom = document.getElementById('TencentCaptcha1');      if (!captchaDom) {        return;      }      this.tencentRecaptcha = new TencentCaptcha(        captchaDom, appId, (res) => {          this.captchaValid = false;          console.log(res);          // res(用戶主動關閉驗證碼)= {ret: 2, ticket: null}          // res(驗證成功) = {ret: 0, ticket: "String", randstr: "String"}          if (res.ret === 0) {            this.captchaInfo.nonce = res.randstr;            this.captchaInfo.ticket = res.ticket;            this.captchaValid = true;            this.tencentRecaptcha.destroy();              let button = <HTMLElement>document.getElementById("btnSubmit");            button.click();          }        }      );      console.log(`captcha inited`);      this.tencentRecaptcha.show();    }

使用效果:

老版網站接入效果:

Reference