zoukankan      html  css  js  c++  java
  • python_way ,day23 API

     python_way ,day23

    1、api认证  、api加密动态请求

    2、自定义session


    一、api认证

    首先提供api的公司,如支付宝,微信,都会给你一个用户id,然后还会让你下一个SDK,你使用SDK加上id做加密,访问商提供的域名进行验证

    SDK,一个商户的加密程序。

    二、动态地址认证:

    为了避免黑客拦截你提交的请求,然后使用你提交的请求非法获取利益,所以我们就需要每次提交都需要改变一下url,这下你使用过的url就失去了作用。

    (但是前提是你必须在他之前访问,如果比他访问的慢那就没有办法了)

    所以我们就是制作一个动态的url给服务器

     比如说md5与时间拼接后的字符串进行加密,就是服务器商提供的SDK我们使用它对服务器给我们提供的id进行加密

    1.NB的加密算法:

    #!/usr/bin/env python3
    # Created by han on 2016/10/28
    import hashlib
    import time
    
    #客户端的操作没客户端获取了服务器事先给的asdfasdf,这个值,然后使用官方规定的加密方法,这里就是用的md5做加密,然后把加密后的数值传给服务器,服务器用相同的方法解密
    def md5(arg):
        m = hashlib.md5()
        m.update(bytes(arg,encoding="utf8"))
        return m.hexdigest()
    
    
    def new_str(arg):
        current_time = time.time()
        rer_str = "%s|%s" % (arg,current_time)
        md5_str = md5(rer_str)
        return md5_str,current_time     #还需要把时间给服务器返回,好让他使用这个动态的字符串解密

    2、向服务商提请求

    #!/usr/bin/env python3
    # Created by han on 2016/10/28
    import os,sys
    sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    import requests
    from module import client_publish
    # key = "asdaf"  #因为静态的api会让黑客截取
    row_key = client_publish.new_str("asdfasdf")        #row_key 是一个元组,上面返回的包括(加密串与当前时间)
    key="%s|%s" % row_key         
    ret = requests.get("http://www.old.com:8888/main?app_id=%s"%key)   #使用get方式请求服务器
    print(ret.text)

     3、服务商接收请求,并且获取到动态的url,进行加密校验

    import os,sys, time
    sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    import tornado.web
    from module import client_publish
    APP_ID_LIST = [
        'asdf',
        '123',
        'asdfasdf',
    ]
    
    
    class MainHadler(tornado.web.RequestHandler):
        def get(self):
            md5_app_id = self.get_argument("app_id", None)  #获取get的携带的请求
         #先分割,获取时间与客户端的加密字符串
            time = md5_app_id.split("|")[1]
            client_md5 = md5_app_id.split("|")[0]
            #设置一个标志
            flag = False
            for i in APP_ID_LIST:
                server_str = "%s|%s" % (i, time)
                server_md5 = client_publish.md5(server_str)
                #这里也做md5加密,如果值和客户端传过来的值相等,那么就可以证明验证通过
           if server_md5 == client_md5:
                    flag = True
              break #认证成功后跳出  
    if flag: self.write("APP_ID") #相当于django的HTTPResponse else: self.write("")

    但是这样貌似加密了,劫持后所有动态的url都可以使用!

    所以我们就要规定一个有效时间,这个有效时间内他同一个客户端传来的url只能访问一次

    然后把这些已经访问过得url存到redis,redis,指定这个redis中定期的数据清除。

    #!/usr/bin/env python3
    # Created by han on 2016/10/26
    import os, sys, time
    sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    import tornado.web
    from module import client_publish
    APP_ID_LIST = [
    'asdf',
        '123',
        'asdfasdf',
    ]
    
    valide_url = []    #这个列表就是维护一个已经验证通过,并且使用过的url,我们可以把这个列表放到redis中,每大于10秒清空它
    
    class MainHadler(tornado.web.RequestHandler):
    def get(self):
      st = time.time()    #先生成本地时间
      md5_app_id = self.get_argument("app_id", None)  #获取get的携带的请求
      client_md5, client_time = md5_app_id.split("|")
      if float(client_time) < st - 10:        #判断一,假如在10s内再次访问。不通过
        self.write("滚1") 
        return
       if md5_app_id in valide_url:            #如果md5在valid_url中,证明已经验证过了,不通过
        self.write("滚2")
        return
      flag = False
       for i in APP_ID_LIST:                
        server_str = "%s|%s" % (i, client_time)  , #如果黑客修改了时间,到这里利用时间做md5值加密的时候就和用户发来的不一样了!所有就能规避到用户发来的修改时间后的rul了
        server_md5 = client_publish.md5(server_str)
      if server_md5 == client_md5:    #到这里就应该是第一次访问,并且通过了正确性验证
        flag = True
        valide_url.append(md5_app_id)    #因为是第一次访问,所以把刚刚验证的url添加到列表中
        break  #认证成功后跳出
      if flag:
        self.write("APP_ID")   #相当于django的HTTPResponse
      else:
        self.write("滚3")
    
    class CmdbHander(tornado.web.RequestHandler): #tornado内部使用反射来找到类中对应的方法
    #resutful变向资源编程,一个url通过不同的请求分配到不同的方法
    def get(self):
    # self.write("cmdb")
    a = [11, 22, 33, 44]
    self.render("index.html", li = a)
    
    def post(self):                                   #以post方式请求,
    user_info = []
    user = self.get_argument("user")              #获取post请求的信息
    pwd = self.get_argument("password")
    user_info.append({"u": user, "p": pwd})
    self.redirect('/home')                           #跳转
    
    
    class HomeHadler(tornado.web.RequestHandler):
    def get(self):
    self.render("home.html", user_info_list = USER_INFO)       #模板渲染
    #!/usr/bin/env python3
    # Created by han on 2016/10/28
    import os,sys
    sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    import requests
    from module import client_publish
    # key = "asdaf"  #因为静态的api会让黑客截取
    row_key = client_publish.new_str("asdfasdf")
    key="%s|%s" % row_key
    ret = requests.get("http://www.old.com:8888/main?app_id=%s"%key)   #使用get方式请求服务器
    print(ret.text)

    二、自定义session 

     cookie:写在浏览器上的一个键值对

    session:写在服务器上的,key就是cookie的value,value里是对应的一些值

    Django,session使用时用到了类中的一个方法。

    session的预备知识:

    1、定义字典样式

    2、反射

    class Text:
        def get(self):
            print("get")
        def set(self):
            print("set")
    
    obj = Text()
    func = getattr(obj,'get')
    func()
    反射

    3、tornado执行类方法的钩子:

    #我们在请求cmdb.old.com/home的时候直接执行了 HomeeHadler中的get方法
    #是应为Tonardo内部肯定将 HomeHadler实例化了
    # obj = HomeHadler()
    # obj.get()
    #如果我们想在执行get方法前添加一个方法,哪我们就要讲HomeHadler的构造方法中添加一个功能,就可以了
    #HomeHadler我们没有写构造方法,哪我们就去找他的父类的构造方法
    #在tornado.web.RequestHandler内部我们看到了这个钩子,是预留好的,自己可以自定义的
        # def initialize(self):
        #     pass
    #我们就可以修改源码了,但是如果修改了源码,哪我们在线上线下布置的环境中就都需要修改这个源码,
    #所以我们就使用继承的方式,将这个initialize使用上

    class HomeHadler(tornado.web.RequestHandler):
        def initialize(self):
            print("123123")              #此时就会先执行initialize
    
        def get(self):
            self.write("OK")

    如果一个类使用上面的解决方式就可以实现了。但是如果要是很多类都需要使用initialize方法,并且还需要修改,上面的方法就有些蠢了

    那么我们就可以使用一个继承来解决这个问题了。

    class MyRequestHandler(tornado.web.RequestHandler):
        def initialize(self):
            print("123123")
    
    class HomeHadler(MyRequestHandler):
    
        def get(self):
            self.write("OK")
            
    class HostHadler2(MyRequestHandler):   #这种方式的话就可以方便统一使用,统一修改了
        def get(self):
            self.write("OK")

     思考:

    HomeHadler 或者 HostHadler2中的self和  MyRequestHandler中的self是否一样
    是一样的
    因为在我们创建对象的时候
    obj = HostHadler()
    obj.initialize() 如果在HomeHadler中没有,就回去他的父类MyRequestHandler中寻找,所以他们两个obj对象是一个,这样就可以判断出self是一个了
    答案

     所以我们就可以把代码改动一下做个试验

    lass MyRequestHandler(tornado.web.RequestHandler):
        def initialize(self):
            self.sss = {"k",123}
    
    class HomeHadler(MyRequestHandler):
    
        def get(self):
            print(self.sss)
            self.write("OK")

    这会执行结果就是
    "k",123

    言归正传:给浏览器的cookie设置session

    application = tornado.web.Application([
    (r"/main", home.MainHadler),
    ], **settings) #只需要在application这里增加setttings这个配置

    application.add_handlers("cmdb.old.com",[
    (r"/home", home.HomeHadler),
    ])
    container = {}
    
    class Session:
        def __init__(self, handler):        #3、handler就是之前传递过来的handler方法,所以它也会有setcookie方法。
            self.cookie = client_publish.md5_str()  #先生成一个变化的cookie
            client_cookie = handler.get_cookie("__session_id__")    #获取客户端的cookie
            if client_cookie:                                       #如果获取到cookie
                if client_cookie in container:                      #检查这个cookie是否存在在container中
                    #如果客户端访问的md5在我的列表中证明是真的
                    print("有cookie")                        
                    self.r_str = client_cookie                      #设置一个字段,以备以后调用
                else:#否则就是假的
                    handler.set_cookie("__session_id__",self.cookie)            #设置一个新的cookie
                    print("假的cookie")
                    container[self.cookie] = {}                                 #把这个cookie放在字典中
                    self.r_str = self.cookie                                    #同样因为是新生成的cookie,还是设置一个字段,以备后患
            else:
                container[self.cookie] = {}                                     #如果没有设置cookie,第一次访问
                print("没有cookie")   
                handler.set_cookie("__session_id__", self.cookie)               #设置cookie
                self.r_str = self.cookie
    
    
    class MyRequestHandler(tornado.web.RequestHandler):
        def initialize(self):                  ##2、执行这个initalize函数
            #在RequestHandler中有set_cookie方法
            self.key = Session(self)  #我们把self传递给Session 自定义的这个类中
    
    class HomeHadler(MyRequestHandler):        ##  1、第一部会先执行这个函数并向客户端浏览器会写 set cookie,但在回写之前,执行了父类中的构造函数
        def get(self):
            #self.set_cookie()   因为这里继承了MyRequestHandler,所以在这里也有set cookie方法
            self.write("set cookie")
    
    
  • 相关阅读:
    Windows / Linux / MacOS 设置代理上网的方法汇总
    Centos7 配置 sendmail、postfix 端口号25、465
    CentOS 6/7 配置 sendEmail 发送邮件
    Python 发送 email 的三种方式
    Linux curl 命令模拟 POST/GET 请求
    Python + Selenium + Chrome 使用代理 auth 的用户名密码授权
    Python + Selenium + Firefox 使用代理 auth 的用户名密码授权
    Jenkins+JMeter+Ant 接口持续集成
    接口自动化、移动端、web端自动化如何做?
    pytest--命令行参数
  • 原文地址:https://www.cnblogs.com/python-way/p/6009754.html
Copyright © 2011-2022 走看看