文章来源: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()
|