文章来源:http://slaytanic.blog.51cto.com/2057708/1638403/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
class SigninHandler(BaseHandler): #引入BaseHandler def post( self ): #HTTP的POST方法,是GET渲染的form中的post method所对应 username = self .get_argument( 'username' ) #获取form中username的值 password = self .get_argument( 'password' ) #获取form中password的值 conn = MySQLdb.connect( 'localhost' , user = 'root' , passwd = ' ', db = ' datacenter ', charset = ' utf8', cursorclass = MySQLdb.cursors.DictCursor) #连接数据库,指定cursorclass的目的是要让返回结果以字典的形式呈现,如果不写,是以元组形式返回 cursor = conn.cursor() #定义数据库指针 sql = 'SELECT * FROM dc_users WHERE username=%s AND password=password(%s)' #写sql,为何这样写后面再说 cursor.execute(sql, (username, password,)) #执行SQL row = cursor.fetchone() #获取一条,返回值为dict,因为前面连接数据库时定义了cursorclass = MySQLdb.cursors.DictCursor,当然,你需要import MySQLdb.cursors的包 if row: #如果存在记录 self .set_secure_cookie( 'id' , str (row[ 'id' ]).encode( 'unicode_escape' ), expires_days = None ) #设置安全cookie,防止xsrf跨域 self .set_secure_cookie( 'username' , row[ 'username' ].encode( 'unicode_escape' ), expires_days = None ) #same self .set_secure_cookie( 'role' , row[ 'role' ].encode( 'unicode_escape' ), expires_days = None ) #same ip = self .request.remote_ip #获取来访者IP sql = 'UPDATE dc_users SET last_access = NOW(), last_ip=%s WHERE id = %s' #认证审计变更的SQL cursor.execute(sql, (ip, row[ 'id' ],)) #执行SQL conn.commit() #提交执行 cursor.close() #关闭指针 conn.close() #关闭数据库连接 self .redirect( '/' ) #转入首页 return #返回,按照官方文档的要求,在redirect之后需要写空的return,否则可能会有问题,实测确实会有问题 else : #如果不存在记录 self .redirect( '/Signin' ) #跳转回登录页面 return def get( self ): #HTTP GET方式 self .render( 'users/login_form.html' ) #渲染登录框HTML |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
{% include 'header.html' %} <!--引入header文件,需要跟login_form在同一路径下,否则写相对路径,如 {% include '../header.html' %} --> < div class = "container" > < h2 >< script >document.write(language.Title + ' ' + language.Version + ' - ' + language.Codename)</ script ></ h2 > < form class = "form-horizontal" method = "post" action = "/Signin" > <!--这里的action对应的上面Python代码中SigninHandler的post方法--> {% module xsrf_form_html() %} <!--防跨域cookie模块--> < div class = "form-group" > < label class = "col-sm-2 control-label" >< script >document.write(language.Username + language.Colon)</ script ></ label > < div class = "col-sm-4" >< input class = "form-control" type = "text" name = "username" placeholder = "Username" ></ div > </ div > < div class = "form-group" > < label class = "col-sm-2 control-label" >< script >document.write(language.Password + language.Colon)</ script ></ label > < div class = "col-sm-4" >< input class = "form-control" type = "password" name = "password" placeholder = "Password" ></ div > </ div > < div class = "form-group" > < div class = "col-sm-2" ></ div > < div class = "col-sm-4" > < button type = "submit" class = "col-sm-4 btn btn-info" >< script >document.write(language.Signin)</ script ></ button > </ div > </ div > </ form > </ div > {% include 'footer.html' %} |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
#-*- coding: utf-8 -*- import sys reload (sys) sys.setdefaultencoding( 'utf-8' ) import tornado.ioloop import tornado.web import tornado.httpserver import tornado.autoreload import os class BaseHandler(tornado.web.RequestHandler): #BaseHandler def get_current_user( self ): user = self .get_secure_cookie( 'username' ) return user class IndexHandler(BaseHandler): @tornado.web.authenticated def get( self ): if not self .current_user: self .redirect( '/Signin' ) #如未登录,则跳转Signin,Signin的GET方法调用的就是login_form.html页面 return self .render( 'welcome.html' ) #否则渲染welcome.html settings = \ { "cookie_secret" : "HeavyMetalWillNeverDie" , #Cookie secret "xsrf_cookies" : True , #开启跨域安全 "gzip" : False , #关闭gzip输出 "debug" : False , #关闭调试模式,其实调试模式是很纠结的一事,我喜欢打开。 "template_path" : os.path.join(os.path.dirname(__file__), "./templates" ), #定义模板,也就是login_form.html或header.html相对于本程序所在的位置 "static_path" : os.path.join(os.path.dirname(__file__), "./static" ), #定义JS, CSS等文件相对于本程序所在的位置 "login_url" : "/Signin" , #登录URL为/Signin } application = tornado.web.Application([ (r "/" , IndexHandler), #路由设置/ 使用IndexHandler (r "/signin" , SigninHandler) # Signin使用SigninHandler ], * * settings) if __name__ = = "__main__" : #启动tornado,配置里如果打开debug,则可以使用autoload,属于development模式,如果关闭debug,则不可以使用autoload,属于production模式。autoload的含义是当tornado监测到有任何文件发生变化,不需要重启server即可看到相应的页面变化,否则是修改了东西看不到变化。 server = tornado.httpserver.HTTPServer(application) server.bind( 10002 ) #绑定到10002端口 server.start( 0 ) #自动以多进程方式启动Tornado,否则需要手工启动多个进程 tornado.ioloop.IOLoop.instance().start() |