創(chuàng)新互聯(lián)www.cdcxhl.cn八線動(dòng)態(tài)BGP香港云服務(wù)器提供商,新人活動(dòng)買多久送多久,劃算不套路!
專業(yè)成都網(wǎng)站建設(shè)公司,做排名好的好網(wǎng)站,排在同行前面,為您帶來(lái)客戶和效益!創(chuàng)新互聯(lián)建站為您提供成都網(wǎng)站建設(shè),五站合一網(wǎng)站設(shè)計(jì)制作,服務(wù)好的網(wǎng)站設(shè)計(jì)公司,成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)負(fù)責(zé)任的成都網(wǎng)站制作公司!flask驗(yàn)證登錄的方法?這個(gè)問(wèn)題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見(jiàn)到的。希望通過(guò)這個(gè)問(wèn)題能讓你收獲頗深。下面是小編給大家?guī)?lái)的參考內(nèi)容,讓我們一起來(lái)看看吧!
用戶認(rèn)證的原理
在了解使用Flask來(lái)實(shí)現(xiàn)用戶認(rèn)證之前,我們首先要明白用戶認(rèn)證的原理。假設(shè)現(xiàn)在我們要自己去實(shí)現(xiàn)用戶認(rèn)證,需要做哪些事情呢?
首先,用戶要能夠輸入用戶名和密碼,所以需要網(wǎng)頁(yè)和表單,用以實(shí)現(xiàn)用戶輸入和提交的過(guò)程。
用戶提交了用戶名和密碼,我們就需要比對(duì)用戶名,密碼是否正確,而要想比對(duì),首先我們的系統(tǒng)中就要有存儲(chǔ)用戶名,密碼的地方,大多數(shù)后臺(tái)系統(tǒng)會(huì)通過(guò)數(shù)據(jù)庫(kù)來(lái)存儲(chǔ),但是實(shí)際上我們也可以簡(jiǎn)單的存儲(chǔ)到文件當(dāng)中。
登錄之后,我們需要維持用戶登錄狀態(tài),以便用戶在訪問(wèn)特定網(wǎng)頁(yè)的時(shí)候來(lái)判斷用戶是否已經(jīng)登錄,以及是否有權(quán)限訪問(wèn)改網(wǎng)頁(yè)。這就需要有維護(hù)一個(gè)會(huì)話來(lái)保存用戶的登錄狀態(tài)和用戶信息。
從第三步我們也可以看出,如果我們的網(wǎng)頁(yè)需要權(quán)限保護(hù),那么當(dāng)請(qǐng)求到來(lái)的時(shí)候,我們就首先要檢查用戶的信息,比如是否已經(jīng)登錄,是否有權(quán)限等,如果檢查通過(guò),那么在response的時(shí)候就會(huì)將相應(yīng)網(wǎng)頁(yè)回復(fù)給請(qǐng)求的用戶,但是如果檢查不通過(guò),那么就需要返回錯(cuò)誤信息。
在第二步,我們知道要將用戶名和密碼存儲(chǔ)起來(lái),但是如果只是簡(jiǎn)單的用明文存儲(chǔ)用戶名和密碼,很容易被“有心人”盜取,從而造成用戶信息泄露,那么我們實(shí)際上應(yīng)當(dāng)將用戶信息尤其是密碼做加密處理之后再存儲(chǔ)比較安全。
用戶登錄
通過(guò)Flask以及相應(yīng)的插件來(lái)實(shí)現(xiàn)登錄過(guò)程
接下來(lái)講述如何通過(guò)Flask框架以及相應(yīng)的插件來(lái)實(shí)現(xiàn)整個(gè)登錄過(guò)程,需要用到的插件如下:
flask-wtf
wtf
werkzeug
flask_login
使用flask-wtf和wtf來(lái)實(shí)現(xiàn)表單功能
flask-wtf對(duì)wtf做了一些封裝,不過(guò)有些東西還是要直接用wtf,比如StringField等。flask-wtf和wtf主要是用于建立html中的元素和Python中的類的對(duì)應(yīng)關(guān)系,通過(guò)在Python代碼中操作對(duì)應(yīng)的類,對(duì)象等從而控制html中的元素。我們需要在python代碼中使用flask-wtf和wtf來(lái)定義前端頁(yè)面的表單(實(shí)際是定義一個(gè)表單類),再將對(duì)應(yīng)的表單對(duì)象作為render_template函數(shù)的參數(shù),傳遞給相應(yīng)的template,之后Jinja模板引擎會(huì)將相應(yīng)的template渲染成html文本,再作為http response返回給用戶。
定義表單類示例代碼:
from flask_wtf import FlaskForm from wtforms import StringField, BooleanField, PasswordField from wtforms.validators import DataRequired # 定義的表單都需要繼承自FlaskForm class LoginForm(FlaskForm): # 域初始化時(shí),第一個(gè)參數(shù)是設(shè)置label屬性的 username = StringField('User Name', validators=[DataRequired()]) password = PasswordField('Password', validators=[DataRequired()]) remember_me = BooleanField('remember me', default=False)
在wtf當(dāng)中,每個(gè)域代表就是html中的元素,比如StringField代表的是元素,當(dāng)然wtf的域還定義了一些特定功能,比如validators,可以通過(guò)validators來(lái)對(duì)這個(gè)域的數(shù)據(jù)做檢查,詳細(xì)請(qǐng)參考wtf教程。
對(duì)應(yīng)的html模板可能如下login.html:
{% extends "layout.html" %}Login Page
這里{{ form.csrf_token }}也可以使用{{ form.hidden_tag() }}來(lái)替換
同時(shí)我們也可以使用form去定義模板,跟直接用html標(biāo)簽去定義效果是相同的,Jinja模板引擎會(huì)將對(duì)象、屬性轉(zhuǎn)化為對(duì)應(yīng)的html標(biāo)簽,
相對(duì)應(yīng)的template,如下login.html:
{% extends "base.html" %} {% block content %}{% endblock %}Sign In
現(xiàn)在我們需要在view中定義相應(yīng)的路由,并將相應(yīng)的登錄界面展示給用戶。
簡(jiǎn)單起見(jiàn),將view的相關(guān)路由定義放在主程序當(dāng)中
@app.route('/login') def login(): form = LoginForm() return render_template('login.html', title="Sign In", form=form)
這里簡(jiǎn)單起見(jiàn),當(dāng)用戶請(qǐng)求'/login'路由時(shí),直接返回login.html網(wǎng)頁(yè),注意這里的html網(wǎng)頁(yè)是經(jīng)過(guò)Jinja模板引擎將相應(yīng)的模板轉(zhuǎn)換后的html網(wǎng)頁(yè)。
至此,如果我們把以上代碼整合到flask當(dāng)中,就應(yīng)該能夠看到相應(yīng)的登錄界面了,那么當(dāng)用戶提交之后,我們應(yīng)當(dāng)怎樣存儲(chǔ)呢?這里我們暫時(shí)先不用數(shù)據(jù)庫(kù)這樣復(fù)雜的工具存儲(chǔ),先簡(jiǎn)單地存為文件。接下來(lái)就看下如何去存儲(chǔ)。
加密和存儲(chǔ)
我們可以首先定義一個(gè)User類,用于處理與用戶相關(guān)的操作,包括存儲(chǔ)和驗(yàn)證等。
from werkzeug.security import generate_password_hash from werkzeug.security import check_password_hash from flask_login import UserMixin import json import uuid # define profile.json constant, the file is used to # save user name and password_hash PROFILE_FILE = "profiles.json" class User(UserMixin): def __init__(self, username): self.username = username self.id = self.get_id() @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self, password): """save user name, id and password hash to json file""" self.password_hash = generate_password_hash(password) with open(PROFILE_FILE, 'w+') as f: try: profiles = json.load(f) except ValueError: profiles = {} profiles[self.username] = [self.password_hash, self.id] f.write(json.dumps(profiles)) def verify_password(self, password): password_hash = self.get_password_hash() if password_hash is None: return False return check_password_hash(self.password_hash, password) def get_password_hash(self): """try to get password hash from file. :return password_hash: if the there is corresponding user in the file, return password hash. None: if there is no corresponding user, return None. """ try: with open(PROFILE_FILE) as f: user_profiles = json.load(f) user_info = user_profiles.get(self.username, None) if user_info is not None: return user_info[0] except IOError: return None except ValueError: return None return None def get_id(self): """get user id from profile file, if not exist, it will generate a uuid for the user. """ if self.username is not None: try: with open(PROFILE_FILE) as f: user_profiles = json.load(f) if self.username in user_profiles: return user_profiles[self.username][1] except IOError: pass except ValueError: pass return unicode(uuid.uuid4()) @staticmethod def get(user_id): """try to return user_id corresponding User object. This method is used by load_user callback function """ if not user_id: return None try: with open(PROFILE_FILE) as f: user_profiles = json.load(f) for user_name, profile in user_profiles.iteritems(): if profile[1] == user_id: return User(user_name) except: return None return None
User類需要繼承flask-login中的UserMixin類,用于實(shí)現(xiàn)相應(yīng)的用戶會(huì)話管理。這里我們是直接存儲(chǔ)用戶信息到一個(gè)json文件"profiles.json"我們并不直接存儲(chǔ)密碼,而是存儲(chǔ)加密后的hash值,在這里我們使用了werkzeug.security包中的generate_password_hash函數(shù)來(lái)進(jìn)行加密,由于此函數(shù)默認(rèn)使用了sha1算法,并添加了長(zhǎng)度為8的鹽值,所以還是相當(dāng)安全的。一般用途的話也就夠用了。驗(yàn)證password的時(shí)候,我們需要使用werkzeug.security包中的check_password_hash函數(shù)來(lái)驗(yàn)證密碼get_id是UserMixin類中就有的method,在這我們需要overwrite這個(gè)method。在json文件中沒(méi)有對(duì)應(yīng)的user id時(shí),可以使用uuid.uuid4()生成一個(gè)用戶唯一id。
感謝各位的閱讀!看完上述內(nèi)容,你們對(duì)flask驗(yàn)證登錄的方法大概了解了嗎?希望文章內(nèi)容對(duì)大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道。