Tornado 用户注册&登录&登出(User regist&login&logout)
############################################
@Tornad 英文官网
@Tornado 用户认证(User authentication )示例文档
@Tornado 博客(blog)GitHub 示例代码
############################################
##############################################################
环境:
Python 3.6.5 (default, Jun 25 2018, 17:02:26)
tornado 6.0.3
Tornado-MySQL 0.5.1
mysql Ver 14.14 Distrib 5.6.36, for Linux (x86_64) using EditLine wrapper
##############################################################
##################################################################
#HTML 效果图
HTML UserRegis
{% block title %}Please checkout your page-title!{% end %}
{% block body %}Set up you body-block first!
{% end %}
{% block js %}{% end %}
{% block css %}{% end %}
{% extends "base.html"%}
{% block title %}User Regis{% end %} //title
{% block body %} //body
{% end %}
{% block js %}
{% end %}
{% block css %}
{% end %}
HTML UserLogin
{% extends "base.html" %}
{% block title %}Login Page{% end %}
{% block body %}
{% end %}
{% block js %}
{% end %}
{% block css %}
{% end %}
HTML Index&UserLogout
{% extends "base.html" %}
{% block title %}GotIT Now!{% end %}
{% block body %}
Hello {{uname}}, Welcome to GotIT's Main Page!
{% end %}
{% block js %}
{% end %}
###################################################################
##########################
tornado/manage.py #主程序文件 Tornado Web Server
from tornado.web import Application
from tornado import ioloop, gen
from tornado import options
from views import Home, UserLogin, UserLogout, UserRegis
from tornado.options import define ,options, parse_command_line
from ws import WSEcho
define('WEB_HOST', default='192.168.159.133', help='Web Listen address')
define('WEB_PORT', type=int, default=1010, help='Web Listen port')
#重写tornado.web.Application并初始化
class MyApp(Application):
def __init__(self):
#urls正则匹配对应的url,把匹配到的请求推送给对应的view视图接口
urls = [
(r'/index', Home),
(r'/login', UserLogin),
(r'/logout', UserLogout),
(r'/regis', UserRegis),
(r'/ws', WSEcho),
]
#定义Tornado web App初始的设定
settings = dict(
static_path = 'static', #静态文件路径
template_path = 'template', #HTML模板文件路径
cookie_secret = '#404@*#', #cookie加密密码
login_url = '/login', #未认证用户跳转路径
xsrf_cookies = True, #启用xsrf防劫持
debug=True, #启用debug,打印出debug信息
)
super(Application, self).__init__(urls, **settings) #初始化
if __name__ == "__main__":
parse_command_line()
app = MyApp()
app.listen(options.WEB_PORT, options.WEB_HOST) #绑定IP及端口
print(app.settings) #打印出当前设定信息
ioloop.IOLoop.current().start()
tornado/views.py #视图文件 对浏览器(Brower)的请求(Request)进行分类处理
from __future__ import print_function
from tornado.web import RequestHandler, hashlib
from tornado.websocket import WebSocketHandler as ws
from tornado.web import authenticated as authed
from tornado.gen import coroutine
from tornado_mysql import pools
#使用tornado_mysql建立mysql连接池
pools.DEBUG = True
POOL = pools.Pool(dict(host='192.168.159.133', port=3306, user='tornado', passwd='tornado_pass', db='Tornado'),
max_idle_connections=2,max_recycle_sec=3)
#重写RequestHandler类,定义get_current_user功能,使能记录当前登录用户
#当用户登入后会写入一个Cookie [self.set_secure_cookie('uname', uname)]
#tornado的auth模块会调用get_current_user功能返回的cookie值,并记录此cookie值
#代表的用户为登录状态
class req(RequestHandler):
def get_current_user(self):
return self.get_secure_cookie("uname")
class Home(req):
#添加tornado的authenticated修饰,当用户为未认证状态时,跳转到settings定义好的
#[login_url = '/login',] URL
@authed
async def get(self):
uname = self.current_user.decode('utf-8') #获取当前已认证用户名
#render模块把uname代入到template模板[index.html]中替换模板语句jinjia2
#对应的变量{{uname}}
return self.render("index.html", uname=uname)
async def post(self):
return self.write('post')
def delete(self):
return self.write('delete')
#用户登入
class UserLogin(req):
#异步处理客户端GET请求,加快处理请求速度。
async def get(self):
return self.render("login.html", title="User Login Form")
#协程处理花费较长时间的数据库查询事件,不会block Tornado进程。
@coroutine
def post(self):
uname = self.get_argument('uname')
upass = self.get_argument('upass')
text = uname + upass
md5pass = hashlib.md5(text.encode()).hexdigest()
#使用Tornado-Mysql,yield异步处理数据库查询
cur = yield POOL.execute("SELECT password FROM user WHERE name=(%s)", (uname,))
r = cur.fetchone()
cur.close()
if r:
password = r[0]
if password == md5pass:
self.set_secure_cookie('uname', uname)
print(self.current_user)
return self.redirect("/index")
else:
return self.redirect("/login")
else:
return self.redirect("/login")
class UserLogout(req):
async def get(self):
logout = self.get_argument('logout', None)
if logout=='on':
self.clear_cookie("uname")
return self.redirect('/index')
class UserRegis(req):
async def get(self):
return self.render("regis.html")
@coroutine
def post(self):
uname = self.get_argument('uname', None)
upass = self.get_argument('upass', None)
umail = self.get_argument('umail', None)
utell = self.get_argument('utell', None)
text = uname + upass
md5pass = hashlib.md5(text.encode()).hexdigest()
cur = yield POOL.execute("INSERT INTO `user` (`id`, `name`, `password`, `email`, `tel`) VALUES (NULL, %s, %s, %s, %s)",(uname, md5pass, umail, utell,))
cur.close()
return self.redirect('/login')
tornado/mysqldb.py #连接mysql数据库的文件
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
HOSTNAME = '192.168.159.133' #mysql服务器IP
PORT = '3306' #mysql服务端口
DATABASE = 'Tornado' #数据库名称
USERNAME = 'tornado' #数据库用户,需要提前到mysql添加
PASSWORD = 'tornado_pass' #用户密码
URL = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(
USERNAME,
PASSWORD,
HOSTNAME,
PORT,
DATABASE
)
engine = create_engine(URL)
Base = declarative_base(bind=engine)
Session = sessionmaker(engine)
session = Session()
tornado/model.py #数据表的model文件,设计表格结构内容
- python 控制台中,model.create_db()创建数据库
- main函数运行时去检查数据库是否存在,不存在就 model.create_db()
from sqlalchemy import Column, Integer, String
from mysqldb import Base
#创建表
def create_db():
Base.metadata.create_all()
#删除表
def drop_db():
Base.metadata.drop_all()
#User表的类,定义每一列的属性
class User(Base):
id = Column(Integer, primary_key=True, autoincrement=True) #id列每个表都有的自动增长列
name = Column(String(16), primary_key=False, unique=True, nullable=False) #用户名
password = Column(String(32), primary_key=False,unique=False, nullable=False) #密码
email = Column(String(32), primary_key=False, unique=False, nullable=False) #邮箱
tel = Column(String(16), primary_key=False, unique=False, nullable=False) #电话
__tablename__ = 'user' #表名
tornado/ws.py #Tornado Websocket consumer文件,处理ws&wss服务请求
from tornado.websocket import WebSocketHandler as ws
class WSEcho(ws):
def open(self):
print("WebSocket open")
def on_message(self, message): #客户端向服务端发送msg后触发
self.write_message(message) #广播回复msg
def on_pong(self, data):
print(data)
def on_close(self):
print("WebSocket closed")