APIインタフェース認証


以前、api方式でサービス側にデータを渡す処理を説明した「簡単なAPIの実現」という文章を書いたことがありますが、この過程で認証機能はなく、誰がどんな内容を送っても一括して受信するという明らかに不安全性があり、この文章は元の基礎の上で、インタフェース認証機能を追加しました.インタフェース認証方式:方式一:クライアント:
  • は、鍵
  • を定義することによって、
  • 鍵暗号化をサービス側
  • に送信する.
    サービス:
  • サービス側は同じ鍵
  • を定義する.
  • 同じ暗号化アルゴリズムにより、
  • の値が得られる.
  • サービス側が暗号化する値とクライアントから送信された暗号化鍵とを比較する
  • .
    欠点:
  • 鍵固定不変、暗号化後の値固定不変、露出しやすく、安全性が低い
  • 方式二:クライアント:
  • は、鍵
  • を定義することによって、
  • 鍵を現在のタイムスタンプとともに暗号化し、値
  • を得る.
  • は、暗号化鍵をタイムスタンプとともにサービス側
  • に送信する.
    サービス:
  • サービス側は同じ鍵
  • を定義する.
  • 現在のサーバ側時間と送信されたクライアント時間を比較し、120 sなどの許容可能な時間範囲を設定する.サーバの現在時刻-送信クライアント>120 sの場合、false
  • に戻ります.
  • は、サービス側の鍵とクライアント時間とを同じ暗号化アルゴリズムを行い、
  • の値を得る.
  • は、サービス側が暗号化する値とクライアントから送信された暗号化鍵とを比較し、
  • と一致するか否かを示す.
    メリット:
  • 暗号化された鍵は毎回異なり、
  • を解読しにくい.
  • 有効時間を設定し、安全性
  • を増加する.
    欠点:
  • クライアント時間とサービス側時間の差は大きくできません.もし大きすぎて認証に失敗したり、問題を調べにくい場合は、同じクロックサーバを使用して同期
  • を行うことが望ましいです.
    コードの説明は次のとおりです.
    クライアントコード:
    #!/usr/bin/env python
    #coding:utf8
    import json
    import platform
    import psutil
    import urllib,urllib2
    import time
    import hashlib
    from multiprocessing import cpu_count
     
    sys_info={}
    sys_info['system'] = [] 
    sys_info['cpu'] = []
    sys_info['mem'] = [] 
    sys_info['disk'] = []
    sys_info['wip'] = []
    sys_info['apikey'] = []
     
    #    
    system=sys_info['system'].append(platform.uname()[0])
     
    #cpu  
    cpu_count=sys_info['cpu'].append(cpu_count())
     
    #  
    mem = psutil.virtual_memory()
    mem_info = sys_info['mem'].append(mem.total * 1 / (1024**3))
     
    #    
    sdiskusage = psutil.disk_usage('/')
    disk_info =sys_info['disk'].append(sdiskusage.total * 1 / (1024**3))
     
    #  ip
    def pub_ip():
        url = "http://ip.cip.cc"
        wip = urllib2.urlopen(url).readline().rstrip()
        return  wip
    sys_info['wip'].append(pub_ip())
    
    #    
    def Api_key():    
        client_key = "ddfd-grgf-dsgf-dgfd"    #      key
        hash_obj = hashlib.md5()     #  md5  ,     sha256
        time_span = time.time()
        hash_obj.update("%s|%f" %(client_key,time_span))    #    ,  update    
        encryption = hash_obj.hexdigest()    #      
        result = "%s|%f" %(encryption,time_span)
        return result
    sys_info['apikey'].append(Api_key())
     
    if __name__ == '__main__':
        print sys_info
        print json.dumps(sys_info,indent=4,ensure_ascii=False)
        data = urllib.urlencode(query=sys_info)
        print data
        respose = urllib.urlopen(url="http://127.0.0.1:8090/serveradd/", data=data)

    サービス側コード(django):urls.py設定
    url(r'^serveradd/$','app.views.serveradd'),

    ビューコード(views.py)
    def api_valid(data):
        import time,hashlib
        server_key = "ddfd-grgf-dsgf-dgfd"    #      key,         
        try:
            encryption , time_span = data.split("|")
            print "------->" ,encryption
            print "------->" ,time_span
            time_span = float(time_span)
            #time.sleep(6)    #        
            now_time = time.time()
            if (now_time - time_span) > 5:
                print "  ,    "
                return False
            hash_obj = hashlib.md5()    #  md5  
            print "hash_obj------------",hash_obj
            
            hash_obj.update("%s|%f" %(server_key,time_span))     #    ,  update    
            print hash_obj.hexdigest()    #      
            if hash_obj.hexdigest() == encryption:
                return True
            else:
                print "            ,    ."
                return False
        except Exception,e:
            pass
        return False
        
    def api_auth(func):
        def wrapper(req):
            request_dict = req.POST
            api_key = request_dict.get('apikey')
            api_key = api_key[2:-2]
            print api_key
            if not api_key:
                return HttpResponse("Unauthorized.")
            if not api_valid(api_key):
                return HttpResponse("Unauthorized.")
            return func(req)
        return wrapper
        
    @api_auth
    def serveradd(req):
        if req.method == 'GET':
            print "GET -----error"
        elif req.method == 'POST':
            print "POST method"
            request_dict = req.POST
            print request_dict
            system = request_dict.get('system')
            wip = request_dict.get('wip')
            data = {k: v for k, v in request_dict.items()}
            host = Host.objects.filter(wip=wip).first()
            if not host:
                host = Host(**data)
            host.save(force_insert=True)
        data = {
                'msg': 'ok',
                'status': 'ok'
                }
        return HttpResponse(data)
    
        :
    1.    ,    :
    POST method-------
    
    ----['Darwin']----['14.196.121.237']
    
    2. key   ,                 ,    :
    1ab7370c45587a9d4d0d1d8f28bd09d7|1477795289.186698
    -------> 1ab7370c45587a9d4d0d1d8f28bd09d7
    -------> 1477795289.186698
    e9d558f11074410464d1769fb2930e81
                ,    。
    
    3.        (         5s,          6s ),                 ,    :
    9dc916fbb04c1310cece3aaa5b2d1b7e|1477795521.379039
    -------> 9dc916fbb04c1310cece3aaa5b2d1b7e
    -------> 1477795521.379039
      ,