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