python123平台登陆页_从头搭建一个flask鉴权系统之登陆

从今天开始,准备从头开始搭建一个基于flask的鉴权系统,一点一滴,积累于生活”

从登陆开始

01.

知识树

本文涉及到如下知识点

1. flask-login的简单使用

2. 本地鉴权实践

3. GitHub鉴权登陆实践,flask-github使用

4. 可扩展的表结构设计思路

02.

表结构设计

我们首先设计一个User用户表,里面的字段可以包括username,password,email等用户信息,大致如下usernamepasswordemailuser1p1user1@gmail.com

user2p2user2@gmail.com

user3p3user3@gmail.com

因为我们还会涉及到第三方登陆,那么为了后面便于扩展,再设计一张表,就命名为ThirdAuth,里面可以包括user_id,与user表关联,oauth_name,oauth_access_token等字段user_idoauth_nameoauth_access_tokenuser-id1auth1token1

user-id2auth2token2

user-id3auth3token3

这样,oauth_name字段可以用来存储第三方来源,例如github,以此来区别不同的第三方登陆用户。

到此,一个简单的表结构就设计好了。

03.OAuth鉴权

简单来说,为一个网站添加第三方登录指的是提供通过其他第三方平台账号登入当前网站的功能。比如,使用QQ、微信、新浪微博账号登录。对于某些网站,甚至可以仅提供社交账号登录的选项,这样网站本身就不需要管理用户账户等相关信息。对用户来说,使用第三方登录可以省去注册的步骤,更加方便和快捷。这里,我就是使用GitHub的OAuth认证来进行鉴权登陆。

这里首先需要在自己的GitHub上创建一个OAuth程序,非常简单,访问这个地址:https://github.com/settings/applications/new,按照要求填写即可。

其中的callback需要填写一个回调函数,具体后面再说。

创建好这个OAuth程序后,我们就会获得Client ID(客户端ID)和Client Secret(客户端密钥),在后面调用Github的API时使用。

04. 本地鉴权

1. 创建表结构

根据刚才的表结构设计,对于本地鉴权,可以在models.py文件中创建一个WebUser类,定义对应的数据库字段。

对于password,不建议直接在数据库中存储明文,所以这里使用了werkzeug库来做hash转换。

同时WebUser类还继承自flask-login的UserMixin类,该类实现了关键的用于检测用户状态的方法:

is_authenticated,如果用户已经登陆返回True,否则返回False

is_active,如果用户允许登陆,返回True,否则返回Flase

is_anonymous,对普通用户必须返回False

get_id,必须返回用户的唯一标识

后面主要使用到了

is_authenticated方法。

而init_user是用来初始化第一个用户的,password等几个方法分别是用来检测密码是否正确的。

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. 定义登陆表单

登陆表单比较简单,两个输入框,分别为用户名和密码,一个check box,用来选择是否保持登陆,外加一个提交按钮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. 定义登陆登出函数

当表单正确提交时,如果用户名和密码匹配,则提示登陆成功,并跳转页面,否则提示登陆失败。

因为是使用flask-login扩展,所以登陆直接调用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装饰器保证只有已经登陆的用户才能调用该函数。@auth.route("/logout")

@login_required

def

logout

():

flash(

"Youhaveloggedout!")

returnredirect(url_for(

"main.index"))

4. web模板

创建一个base.html基础模板(继承自flask-bootstrap模板),后面其他页面都继承自该模板,这样可以保证所有的页面风格统一,也可以减少代码量。

{%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. 初始化数据库

使用flask-script扩展,定义runserver和shell两个命令行命令,shell用于数据库等调测操作,runserver用于启动服务。

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,进入调测shell,然后输入db.create_all()和WebUser.init_user(),分别创建表并插入原始用户。

7. 登陆测试

在输入框分别键入admin@163.com和123456,并点击登陆,发现可以正常登陆,效果如下

其中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%}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值