zoukankan      html  css  js  c++  java
  • python_tornado_session用户验证

    什么是session?

           -- Django中带有session,tornado中自己写

           -- 逻辑整理

          用户请求过来,验证通过,随机生成一个字符串当作value返回给浏览器,

          在服务器中用户信息与随机生成一个字符串建立对应关系,

          下次用户请求带来了cookie,通过字符串找到对应的用户信息。

      -- 优点:一切与用户相关的信息都保存在客户端中,

           用户端无法获取除了随机字符串其他信息,解决了信息隐患

    基于session做用户验证如何做?

           -- 定义一个全局字典

           -- 验证用户,失败跳转到登录页面

           -- 成功 >>生成随机字符串 映射用户信息,登陆状态为True

          >>设置cookie,value=随机字符串

      -- 下次访问,通过cookie中value,找到映射的用户信息,

        找打登录状态,为Ture跳转到成功页面,为False,跳转到登录界面

    #!/usr/bin/python3
    
    import tornado.web
    import tornado.ioloop
    import time
    import hashlib
    
    user_login = {}
    class HomeHandle(tornado.web.RequestHandler):
    
        def get(self, *args, **kwargs):
            if self.get_argument('u') in ['yizhihua', 'beimenchuixue']:      # 判断是合法用户
    
                m = hashlib.md5()                                   # 通过md5获得随机值
                m.update(bytes(str(time.time()), encoding='utf-8'))
                random_str = m.hexdigest()
    
                user_login[random_str] = {}                         # 全局变量新增一个用户信息字典
                user_login[random_str]['username'] = self.get_argument('u')
    
                if self.get_argument('u') == 'yizhihua':            # 把yizhihua用户信息设置不可登录状态
                    user_login[random_str]['login_status'] = False
                else:
                    user_login[random_str]['login_status'] = True   # 其他用户可以登录
    
                self.set_cookie('yi_ye', random_str)
            else:
                self.write('请登陆')
    
    class ManHandle(tornado.web.RequestHandler):
    
        def get(self, *args, **kwargs):
    
            random_str = self.get_cookie('yi_ye')                   # 获得cookie对应的随机字符串
    
            if user_login.get(random_str, None):                    # 尝试取值,没有相当于没有验证
                if user_login[random_str].get('login_status', None):    # 判断用户是否可登录状态
                    temp = '%s-%s' % (user_login[random_str].get('username', ''),
                                      user_login[random_str].get('login_status', ''))
                    self.write(temp)                                # 打印登录成功界面
                else:
                    self.redirect('/home')                          # 返回验证
            else:
                self.redirect('/home')                              # 返回验证
    
    setting = {
        'template_path': 'template',
        'cookie_secret': 'yes'
    
    }
    
    Appliaction = tornado.web.Application(
        [(r'/home', HomeHandle),
         (r'/manager', ManHandle),
         ], **setting
    )
    
    if __name__ == '__main__':
        Appliaction.listen(9999)
        tornado.ioloop.IOLoop.instance().start()
    

      -- 启动,通过http://127.0.0.1:9999/home?u=yizhihua 进行验证

      上面代码有问题,session部分应该很多地方需要验证,

      每个函数都写一个,显得太low了,如何解决?通过类

    如何把session定义成一个类?

      逻辑整理:

           class Session():

                  def __init__(self,)

                  def __random_str()

                         -- 生成随机字符串

                  def set_value(self):

                         -- 获得一个随机的数据

                         -- 定义自己唯一的数据

                         -- 写入随机字符串

                  def get_value()

                         -- 获得客户端随机字符串

                         -- 取自己的数据

                         -- 专属信息key

    #!/usr/bin/python3
    
    import tornado.web
    import tornado.ioloop
    
    user_info = {}
    # 输入 self
    # 内部逻辑 验证用户 生成随机字符串  添加对应用户信息  更改登录状态  发送cookie  获得cookie ,验证,检查登录状态  取出用户信息
    # 输出 通过外部参数获得对应的参数
    class Session(object):
        """Session验证"""
        def __init__(self, handler, cookie_key, url_home):  # self对象,cookie的key,url_home跳转主页url
            self.handler = handler                          # self 对象
            self.cookie_key = cookie_key                    # cookie的key
            self.url_home = url_home                        # 验证主页
    
        def __get_random_str(self):
            """获得随机字符串"""
            import time
            import hashlib
            m = hashlib.md5()
            m.update(bytes(str(time.time()), encoding='utf-8'))
            return m.hexdigest()
    
        def set_value(self, get_name, user_status):
            """用户验证"""
            if self.handler.get_argument(get_name) in ['yizhihua', 'beimenchuixue']:    # 验证用户
                random_str = self.__get_random_str()
                user_info[random_str] = {}                                              # 初始化用户信息表
                user_info[random_str]['username'] = self.handler.get_argument(get_name)
                user_info[random_str]['user_status'] = user_status
                user_info[random_str]['work'] = 'student'
                user_info[random_str]['addr'] = '湖南'
    
                self.handler.set_cookie(self.cookie_key, random_str)        # 设置cookie
                self.handler.redirect('/manager')                           # 验证成功跳转到/manager页面
            else:
                self.handler.redirect(self.url_home)                        # 验证失败重新验证
    
        def get_value(self, user_key):
            """取cookie值,取用户信息"""
            random_str = self.handler.get_cookie(self.cookie_key, None)
            if random_str:                                                  # 判断是否有对应的cookie值
                if random_str in user_info:                                 # 验证cookie
                    if user_info[random_str].get('user_status', None):      # 判断可登录状态
                        return user_info[random_str].get(user_key, None)    # 取值
                    else:
                        self.handler.write('不可登录状态')
                else:
                    self.handler.redirect(self.url_home)
            else:
                self.handler.redirect(self.url_home)
    
    
    class Home(tornado.web.RequestHandler):
        
        def get(self, *args, **kwargs):
            self.render('home.html')                                        # form表单
    
    
    class HomeHandle(tornado.web.RequestHandler):
    
        def get(self, *args, **kwargs):
            session = Session(self, 'yi_ye', '/home/')
            session.set_value('u', True)
    
    class ManHandle(tornado.web.RequestHandler):
    
        def get(self, *args, **kwargs):
    
            session = Session(self, 'yi_ye', '/home')
            work = session.get_value('work')
            addr = session.get_value('addr')
            print(work, addr)
    
    
    
    setting = {
        'template_path': 'views',
        'cookie_secret': 'yes'
    
    }
    
    
    Appliaction = tornado.web.Application(
        [(r'/home', HomeHandle),
        (r'/home/', Home),
         (r'/manager', ManHandle),
         ], **setting
    )
    
    
    if __name__ == '__main__':
        Appliaction.listen(9999)
        tornado.ioloop.IOLoop.instance().start()
    

      

    如何在这个session类中调用处理函数中的方法?

      -- 可以把class逻辑处理类中的self对象当做参数传入进来,

        然后通过session类__init__析构函数给self对象进行重新命名,

        然后就通过新的名字调用class逻辑处理类中的任何方法

    上面的方式并没有实现面向过程,如何实现?

      --start.py    写入

    #!/usr/bin/python3
    import tornado.web
    import tornado.ioloop
    user_info = {}      # 临时存放用户信息列表
    user_eyes = [{'yizhihua': '18'}, {'hehe': '19'}]
    # 入 self 验证 生成cookie 更改用户可登录状态
    class Session(object):
        """session验证"""
        def __init__(self, handler):
            self.handler = handler
    
        def __get_random_str(self):
            """生产随机数"""
            import time, hashlib
            m = hashlib.md5()
            m.update(bytes(str(time.time()), encoding='utf-8'))
            random_str = m.hexdigest()
            return random_str
            pass
    
        def __setitem__(self, key, value):
            """验证登录,设置值"""
            user_name = self.handler.get_argument('user_name')      # 获取前端验证
            pwd = self.handler.get_argument('pwd')
            print(user_name, pwd)
            if {user_name: pwd} in user_eyes:                       # 判断用户合法
                if not self.handler.get_cookie('yi_ye', None):      # 如果cookie存在,不生成随机字符串
                    random_str = self.__get_random_str()                # 生成随机字符串
                else:
                    random_str = self.handler.get_cookie('yi_ye', None)  # 就算是用户伪造cookie也得是验证通过的情况下
                user_info[random_str] = {}                          # 添加用户信息
                user_info[random_str]['user_name'] = user_name
                user_info[random_str]['pwd'] = pwd
                user_info[random_str][key] = value                  # 通过接口设置登录状态
                print(user_info)
    
                self.handler.set_cookie('yi_ye', random_str)            # 生成cookie
                self.handler.render('home.html', user_name=user_name)   # 登录页面
            else:
                self.handler.redirect('/login')                         # 返回登录
    
        def __getitem__(self, item):
            """验证session,获取值"""
            random_str = self.handler.get_cookie('yi_ye', None)         # 获取cookie
            if user_info:                                               # 判断user_info是否有值
                if random_str:                                          # 判断cookie使用有值
                    server_info = user_info.get(random_str, None)       # 判断user_info对应的值
                    if server_info.get('status'):                       # 判断状态
                        return server_info.get(item, None)              # 获取值
                    else:
                        self.handler.redirect('/login')                 # 以上任意一个条件不满足,退回登录界面
                else:
                    self.handler.redirect('/login')
            else:
                self.handler.redirect('/login')
    
    class BaseHandler(tornado.web.RequestHandler):
        """让其他处理类每次都先实例session对象"""
        def initialize(self):
            self.session = Session(self)                                # 实例Session类,self为每个类处理对象
    
    
    # 登录界面不需要session验证,打开隐私界面需要session验证
    
    class Login(BaseHandler):
    
        def get(self, *args, **kwargs):
            self.render('login.html')
    
        def post(self, *args, **kwargs):
            self.session['status'] = True                              # 设置登录状态为True
    
    class Home(BaseHandler):
    
        def get(self, *args, **kwargs):
            if self.session['status']:                                  # 取登录状态
                self.render('home.html', user_name=self.session['user_name'])   # 验证,并模版渲染
    
    
    setting ={
        'template_path': 'views',
        'static_path': 'statics'
    }
    
    Application = tornado.web.Application(
        [
            (r'/login', Login),
            (r'/home', Home),
        ], **setting
    )
    
    if __name__ == '__main__':
        Application.listen(9999)
        tornado.ioloop.IOLoop.instance().start()

      -- login.html  写入

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>login</title>
    </head>
    <body>
        <form action="/login"  method="post">
            <p>账户:<input name='user_name' type="text" ></p>
            <p>密码:<input name='pwd' type="password"></p>
            <p><input type="submit" value="提交"></p>
        </form>
    </body>
    </html>

       -- home.html  写入

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>主页</title>
    </head>
    <body>
        <p><h>欢迎来到{{user_name}}主页</h></p>
        <p><input type="button" value="退出登录"></p>
    </body>
    </html>
    

     如何逻辑整理?

      -- 用户行为:进入登录界面、输入验证信息、提交、进入隐私页面

      -- 服务器行为:验证合法性、成功跳转到隐私页面、设置session_cookie、请求隐私页面验证session,登录界面提交验证不需要验证session

      -- 整个流程:输入验证、提交、后台验证合法性、合法生成session_cookie并且进入隐私页面、失败重新跳转到登录、

            用户请求隐私页面、验证session_cookie、通过则跳转、不通过则跳转到登录界面

      

  • 相关阅读:
    记录一下最近面试的总结
    网络模块相关面试题
    JVM 之类加载器
    一段简单的关于字符串的 Java 代码竟考察了这么多东西
    LeetCode 链表题 ( Java )
    MD5 加盐加密
    SpringMVC 学习笔记
    [redis]dict和rehash
    [redis]SDS和链表
    [go]包和工程管理
  • 原文地址:https://www.cnblogs.com/2bjiujiu/p/6701327.html
Copyright © 2011-2022 走看看