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