Day27 - [丰收款] 永丰线上收款支付API功能实作总结(3) - 如何让机敏性设定值更有保护力

在前一篇文章,我们分析了各个资安防护的强弱要点,但由於固定式的初始四Hash组代码是目前安全性最弱的部份,全仰赖人为保护,若是直接写在Code里面,那一来是作程序码管控时会把具机敏性资料也一起撒出去给其他共同参与开发者外,另一方也降低建置布署若未来有需要修改时的弹性(也就是若这些值要修改,就要重新改code,重新上线)。

所以应该有更好的方式来处理相关的机敏性资料,我们逐一盘点一下,一起修正:

  1. 四组Hash代码:为了产生作为AES Key的HashID,一开始由永丰提供给我们的
  2. ShopNo商店代码:这个看你认为需不需要防护,但提醒一下,取得Nonce值是会需要传出ShopNo的。
  3. DB的资料库密码

接下来我们可以思考如何更有效的管理。

STEP1. 把机敏性属性从Code中抽离出来

我们先前把Hash A1, A2, B1, B2都放在程序码里面,为了验证目的,所以直接这样使用当然最为方便。但我们既然谈到资安是金流服务相当重要的环节,就把这一部份也一起做更优化的处理。

使用settings来读取

我们在settings.py中,可以新增四组Hash代码的属性:

HASH_A1 = "86D50DEF3EB7400E"
HASH_A2 = "01FD27C09E5549E5"
HASH_B1 = "9E004965F4244953"
HASH_B2 = "7FB3385F414E4F91"

然後在使用的code中,原本是这样用的,以sinopacutil.py中的ApiMessage片段:

class ApiMessage:
    shop_no = "NA0249_001"
    api_url = "https://sandbox.sinopac.com/QPay.WebAPI/api/Order"
    A1, A2, B1, B2 = "86D50DEF3EB7400E", "01FD27C09E5549E5", "9E004965F4244953", "7FB3385F414E4F91"

    def __init__(self, api_service):

        self.hash_id = SinopacUtil.get_hash_id(ApiMessage.A1, ApiMessage.A2, ApiMessage.B1, ApiMessage.B2)
    # ... 後面略 ...

原本是直接把这几个值直接写在程序码里,现在从settings中读取,可以改写成这样:

from django.conf import settings

class ApiMessage:
    shop_no = "NA0249_001"
    api_url = "https://sandbox.sinopac.com/QPay.WebAPI/api/Order"
    A1, A2, B1, B2 = settings.HASH_A1, settings.HASH_A2, settings.HASH_B1, settings.HASH_B2

    def __init__(self, api_service):

        self.hash_id = SinopacUtil.get_hash_id(ApiMessage.A1, ApiMessage.A2, ApiMessage.B1, ApiMessage.B2)
    # ... 後面略 ...

如此一来,就完成第一部:不要把设定值hard code在程序码中,这一步和资安没有太大关系,纯粹就日後维护角度来看是比较正确的作法。

如何让他更具安全性

在settings.py中的这些属性目前还是把值直接写在里面,而settings.py是需要被程序码版控的,所以还有改善空间。

这个时候就要引入python好用的环境变数工具dotenv来作管理,首先要先进行套件的安装。dotenv有django-dotenv以及python-dotenv两个不同的套件,版本与用法也不尽相同,但以普偏性而言是python-dotenv较多人使用,参考文献也较多,建议可安装这个。

> pip install python-dotenv

目前我的安装版本是0.19.1版,安装完成後,记得更新到根目录下的requirements.txt档,便於之後作建置时同步安装。

> pip freeze > requirements.txt

dotenv用起来

说了这麽多,到底dotenv要怎麽使用?首先我们要在django project目录底下(mysite/mysite)新增一个.env的档案,里面就是将你需要设定的属性(以全大写命名,建议直接和settings一致)直接定义在这个档里面。

.env档中:

HASH_A1=86D50DEF3EB7400E
HASH_A2=01FD27C09E5549E5
HASH_B1=9E004965F4244953
HASH_B2=7FB3385F414E4F91

注:这不是Python档,所以不需要在字串加上前後的引号

然後我们再回到settings.py中,改写原本直接以明文字串,换成从.env读取进来的系统环境变数。

from dotenv import load_dotenv
load_dotenv()

HASH_A1 = os.getenv('HASH_A1')
HASH_A2 = os.getenv('HASH_A2')
HASH_B1 = os.getenv('HASH_B1')
HASH_B2 = os.getenv('HASH_B2')

在这边,我们需要先引入load_dotenv,在前面先执行load_dotenv().env的环境变数载入。

所以後面的几个环境变数,就可以使用os.getenv()方式将其值载入,如此一来就把实际字串和设定档分开了。

再来,还有要注意的地方

接着,就是要设定.gitignore*.env加入,让这类的档案不要被程序码版控控管。有几个实务上的作法:

  1. 开发者拥有的是「测试Hash代码」,在其开发环境中可自己定义这四组Hash代码字串於本机的.env
  2. 实际Production环境的「正式Hash代码」是由专属的DBA角色控管,届时建置时由他们来管理这部份的资讯
  3. 可撰写一个.env.template档案,里面把所需要的环境变数Key值写好,但Value留空,让程序码下载下来後的开发者,了解自己需要在环境加上哪些环境变数值於.env中。

这样一来,我们就可以有效的将机敏性资料透过这个方式从程序码中区分出来,并且以权责区分方式进行管理与建置工作。

看一下永丰的C# Sample Code

如果你对於C#的程序码有兴趣,可以下载Visual Studio打开Sample的专案程序码 (QPay.SampleCode.sln)
於根目录下,可以看到一个appSettings.config档:

<appSettings>
  <!--Sandbox环境-->
  <!--取得商业收付API 网址-->
  <add key="QPayWebAPIUrl" value="https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/"/>
  
  <!--依商店编号取得商店杂凑值(依A1, A2, B1, B2排序, 商业收付提供)-->
  <add key="NA0001_001" value="65960834240E44B7,2831076A098E49E7,CB1AFFBF915A492B,7F242C0AA612454F"/>
</appSettings>

这边可以看到永丰的C# Sample Code也是将这些会用到的设定值抽离出来放到App设定档中。看到Key为NA0001_001(商店代号)的值,以逗号隔开的就是四个Hash代码。

可以更安全吗?

如果你直接使用ASP.NET的Web专案进行开发,应该会有相对应的web.confg档,而这类的档案里面是会有放置机敏性资料,而最终布署到网站上时并不希望以明码字串写在设定档里面,风险过高。

你可以使用aspnet_regiis的加解密方法,将原先明确字串的设定档,加密为密文,但仍然可以正常使用。
可参考以下文章作法:
https://medium.com/work-insight/secure-your-net-config-files-part-1-251aed4ce4c8
https://ithelp.ithome.com.tw/articles/10231176


<<:  Day 27 LeetCode 212. Word Search II

>>:  DAY 30 Big Data 5Vs – Value(价值) - AWS & YOU

关於商业视角的时间故事

今天谈一个在商业视角的时间故事。 我的公司盛行加班(勿战),因此有些主管为了体恤加班的同仁,也方便把...

android studio 30天学习笔记-day 14-databinding 单向绑定

之前了解了UI的元件跟data之间是如何进行绑定的,那麽在当data发生改变时,又该如何及时让dat...

在k8s上架设ELK教学

【YC的迷路青春】 版本要从头到尾相同ELK都是 这边用7.12.0 原则上就是新增一大堆的yaml...

Day 24 - PVE 修复 Loading initial ramdisk

今天笔者遇到一个问题,系统在开机时卡在 “Loading initial ramdisk”,用了一些...

Lotus Notes to office 365

Lotus Notes to office 365 migration tool is the be...