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、通过则跳转、不通过则跳转到登录界面

  

 

posted @ 2017-04-13 09:26  梦_鱼  阅读(343)  评论(0编辑  收藏  举报