python123平台登陆页_从头搭建一个flask鉴权系统之登陆
“
從今天開始,準(zhǔn)備從頭開始搭建一個(gè)基于flask的鑒權(quán)系統(tǒng),一點(diǎn)一滴,積累于生活”
從登陸開始
01.
知識樹
本文涉及到如下知識點(diǎn)
1. flask-login的簡單使用
2. 本地鑒權(quán)實(shí)踐
3. GitHub鑒權(quán)登陸實(shí)踐,flask-github使用
4. 可擴(kuò)展的表結(jié)構(gòu)設(shè)計(jì)思路
02.
表結(jié)構(gòu)設(shè)計(jì)
我們首先設(shè)計(jì)一個(gè)User用戶表,里面的字段可以包括username,password,email等用戶信息,大致如下usernamepasswordemailuser1p1user1@gmail.com
user2p2user2@gmail.com
user3p3user3@gmail.com
因?yàn)槲覀冞€會涉及到第三方登陸,那么為了后面便于擴(kuò)展,再設(shè)計(jì)一張表,就命名為ThirdAuth,里面可以包括user_id,與user表關(guān)聯(lián),oauth_name,oauth_access_token等字段user_idoauth_nameoauth_access_tokenuser-id1auth1token1
user-id2auth2token2
user-id3auth3token3
這樣,oauth_name字段可以用來存儲第三方來源,例如github,以此來區(qū)別不同的第三方登陸用戶。
到此,一個(gè)簡單的表結(jié)構(gòu)就設(shè)計(jì)好了。
03.OAuth鑒權(quán)
簡單來說,為一個(gè)網(wǎng)站添加第三方登錄指的是提供通過其他第三方平臺賬號登入當(dāng)前網(wǎng)站的功能。比如,使用QQ、微信、新浪微博賬號登錄。對于某些網(wǎng)站,甚至可以僅提供社交賬號登錄的選項(xiàng),這樣網(wǎng)站本身就不需要管理用戶賬戶等相關(guān)信息。對用戶來說,使用第三方登錄可以省去注冊的步驟,更加方便和快捷。這里,我就是使用GitHub的OAuth認(rèn)證來進(jìn)行鑒權(quán)登陸。
這里首先需要在自己的GitHub上創(chuàng)建一個(gè)OAuth程序,非常簡單,訪問這個(gè)地址:https://github.com/settings/applications/new,按照要求填寫即可。
其中的callback需要填寫一個(gè)回調(diào)函數(shù),具體后面再說。
創(chuàng)建好這個(gè)OAuth程序后,我們就會獲得Client ID(客戶端ID)和Client Secret(客戶端密鑰),在后面調(diào)用Github的API時(shí)使用。
04. 本地鑒權(quán)
1. 創(chuàng)建表結(jié)構(gòu)
根據(jù)剛才的表結(jié)構(gòu)設(shè)計(jì),對于本地鑒權(quán),可以在models.py文件中創(chuàng)建一個(gè)WebUser類,定義對應(yīng)的數(shù)據(jù)庫字段。
對于password,不建議直接在數(shù)據(jù)庫中存儲明文,所以這里使用了werkzeug庫來做hash轉(zhuǎn)換。
同時(shí)WebUser類還繼承自flask-login的UserMixin類,該類實(shí)現(xiàn)了關(guān)鍵的用于檢測用戶狀態(tài)的方法:
is_authenticated,如果用戶已經(jīng)登陸返回True,否則返回False
is_active,如果用戶允許登陸,返回True,否則返回Flase
is_anonymous,對普通用戶必須返回False
get_id,必須返回用戶的唯一標(biāo)識
后面主要使用到了
is_authenticated方法。
而init_user是用來初始化第一個(gè)用戶的,password等幾個(gè)方法分別是用來檢測密碼是否正確的。
class
WebUser
(UserMixin,db.Model):
__tablename__=
"webuser"
id=db.Column(db.Integer,primary_key=
True)
user_id=db.Column(db.String(
64),unique=
True,index=
True)
email=db.Column(db.String(
64),unique=
True,index=
True)
username=db.Column(db.String(
64),unique=
True,index=
True)
password_hash=db.Column(db.String(
128))
@staticmethod
def
init_user
():
users=WebUser.query.filter_by(username=
"admin").first()
ifusers
is
None:
users=WebUser(email=
"admin@123.com",username=
"admin",user_id=time.time())
users.password=
"123456"
db.session.add(users)
db.session.commit()
@property
def
password
(self):
raiseAttributeError(
"passwordisnotreadableattribute")
@password.setter
def
password
(self,password):
self.password_hash=generate_password_hash(password)
def
verify_password
(self,password):
returncheck_password_hash(self.password_hash,password)
2. 定義登陸表單
登陸表單比較簡單,兩個(gè)輸入框,分別為用戶名和密碼,一個(gè)check box,用來選擇是否保持登陸,外加一個(gè)提交按鈕class
LoginForm
(FlaskForm):
email=StringField(
"Email",validators=[DataRequired(),Length(
1,
64),Email()])
password=PasswordField(
"Password",validators=[DataRequired()])
remember_me=BooleanField(
"Keepmeloggedin")
submit=SubmitField(
"LogIn")
3. 定義登陸登出函數(shù)
當(dāng)表單正確提交時(shí),如果用戶名和密碼匹配,則提示登陸成功,并跳轉(zhuǎn)頁面,否則提示登陸失敗。
因?yàn)槭鞘褂胒lask-login擴(kuò)展,所以登陸直接調(diào)用login_user()即可。
@auth.route("/login",methods=["GET","POST"])
def
login
():
form=LoginForm()
ifform.validate_on_submit():
user=WebUser.query.filter_by(email=form.email.data).first()
ifuser
is
not
None
anduser.verify_password(form.password.data):
login_user(user,form.remember_me.data)
returnredirect(request.args.get(
"next")
orurl_for(
"main.index"))
flash(
"Invalidusernameorpassword!")
returnrender_template(
"auth/login.html",form=form)
對于登出,同樣簡單,注意需要用login_required裝飾器保證只有已經(jīng)登陸的用戶才能調(diào)用該函數(shù)。@auth.route("/logout")
@login_required
def
logout
():
flash(
"Youhaveloggedout!")
returnredirect(url_for(
"main.index"))
4. web模板
創(chuàng)建一個(gè)base.html基礎(chǔ)模板(繼承自flask-bootstrap模板),后面其他頁面都繼承自該模板,這樣可以保證所有的頁面風(fēng)格統(tǒng)一,也可以減少代碼量。
{%extends"bootstrap/base.html"%}
{%blocktitle%}Flasky{%endblock%}
{%blocknavbar%}
<
div
class=
"navbarnavbar-inverse"
role=
"navigation">
<
div
class=
"container">
<
div
class=
"navbar-header">
<
button
type=
"button"
class=
"navbar-toggle"
data-toggle=
"collapse"
data-target=
".navbar-collapse">
<
span
class=
"sr-only">Togglenavigation
span>
<
span
class=
"icon-bar">
span>
<
span
class=
"icon-bar">
span>
<
span
class=
"icon-bar">
span>
button>
<
a
class=
"navbar-brand"
href=
"/">WebAuth
a>
div>
<
div
class=
"navbar-collapsecollapse">
<
ul
class=
"navnavbar-nav">
<
li><
a
href=
"/">Home
a>
li>
ul>
<
ul
class=
"navnavbar-navnavbar-right">
{%ifcurrent_user.is_authenticated%}
<
li><
a
href=
"{{url_for("auth.logout")}}">SignOut
a>
li>
{%else%}
<
li><
a
href=
"{{url_for("auth.login")}}">SignIn
a>
li>
{%endif%}
ul>
div>
div>
div>
{%endblock%}
{%blockcontent%}
<
div
class=
"container">
{%blockpage_content%}{%endblock%}
div>
{%endblock%}
5. 登陸頁面
登陸頁面繼承自base.html模板,并使用wtf快速渲染表單{%extends"base.html"%}
{%import"bootstrap/wtf.html"aswtf%}
{%blocktitle%}Login{%endblock%}
{%blockpage_content%}
<
div
class=
"page-header">
<
h1>Login
h1>
div>
<
div
class=
"col-md-4">
{{wtf.quick_form(form)}}
div>
{%endblock%}
最后的登陸頁面為
6. 初始化數(shù)據(jù)庫
使用flask-script擴(kuò)展,定義runserver和shell兩個(gè)命令行命令,shell用于數(shù)據(jù)庫等調(diào)測操作,runserver用于啟動服務(wù)。
fromapp
importcreate_app,db
fromflask_script
importManager,Shell,Server
fromapp.models
importWebUser
app=create_app(
"testing")
manager=Manager(app)
def
make_shell_context
():
returndict(app=app,db=db,WebUser=WebUser)
manager.add_command(
"runserver",Server(use_debugger=
True,host=
"0.0.0.0",port=
"9982"))
manager.add_command(
"shell",Shell(make_context=make_shell_context))
if__name__==
"__main__":
manager.run(default_command=
"runserver")
在命令行輸入python manage.py shell,進(jìn)入調(diào)測shell,然后輸入db.create_all()和WebUser.init_user(),分別創(chuàng)建表并插入原始用戶。
7. 登陸測試
在輸入框分別鍵入admin@163.com和123456,并點(diǎn)擊登陸,發(fā)現(xiàn)可以正常登陸,效果如下
其中index頁面代碼為{%extends
"base.html"%}
{%
import
"bootstrap/wtf.html"
aswtf%}
{%blocktitle%}Login{%endblock%}
{%blockpage_content%}
class="
container">
{%
for
message
in
get_flashed_messages
()%}
<
div
class="
alert
alert-
warning">
<
button
type="
button"
class="
close"
data-
dismiss="
alert">&
times;
button>
{{
message}}
div>
{%
endfor%}
div>
<
div
class="
page-
header">
<
h1>
Home
h1>
div>
<
div
class="
col-
md-4">
這是首頁
div>
<
div
class="
col-
md-12">
{%
if
current_user.
is_authenticated%}
{{
current_user.
username}}
{{
name}}
<
div>
<
img
style="-
webkit-
user-
select:none;
"src="{{avatar}}
"/>
{%else%}
Yourarenotloginyet
{%endif%}
總結(jié)
以上是生活随笔為你收集整理的python123平台登陆页_从头搭建一个flask鉴权系统之登陆的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第一百零八期:比较容易理解的Hbase架
- 下一篇: 第五十六期:百度CTO王海峰CNCC20