前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从头搭建一个flask鉴权系统之完结篇

从头搭建一个flask鉴权系统之完结篇

作者头像
周萝卜
发布2019-07-17 15:28:23
9690
发布2019-07-17 15:28:23
举报
文章被收录于专栏:萝卜大杂烩萝卜大杂烩

儿们能喜欢。

从头搭建一个flask鉴权系统之登陆

从头搭建一个flask鉴权系统之角色

从头搭建一个flask鉴权系统之注册

这一篇将会是本系列的最后一篇,让我一起来做个收尾,GO!

知识树

1.集成短信验证码 2.用户资料维护

短信发送demo

使用twilio发短信

我这里使用twilio提供的短信功能,它提供了一个免费的短信接口,让我们可以在完全free的状态下测试短信功能,同时也有对应的python库twilio来简化开发,只需要使用pip install twilio即可使用该公司提供的各种功能。有兴趣的同学可以移步官网查看: https://www.twilio.com/

产生validate code

和前面产生确认邮件的token一样,这里也使用itsdangerous来加密code

代码语言:javascript
复制
 1def generate_code(expiration=3600):
 2    random_num = ''.join(str(i) for i in random.sample(range(0, 9), 4))
 3    s = Serializer(Config.SECRET_KEY, expiration)
 4    return s.dumps({'code': random_num})
 5
 6
 7def decoding_code(code):
 8    s = Serializer(Config.SECRET_KEY)
 9    c = s.loads(code)
10    return c['code']

然后是发送短信的代码,查看官网就可以获得,很简单,不多说了。

代码语言:javascript
复制
1def sendsms(code, num):
2    account_sid = os.environ.get('A_SID')
3    auth_token = os.environ.get('A_TK')
4    mytwilio_num = os.environ.get('T_NUM')
5    client = Client(account_sid, auth_token)
6    message = client.messages.create(
7        from_=mytwilio_num,
8        body=code,
9        to=num)

集成短信功能到系统

新增两个表单,一个是发送verify code,一个是验证verify code

代码语言:javascript
复制
1class LoginSMSCodeForm(FlaskForm):
2    phonenumber = IntegerField('Your Phone Number', validators=[DataRequired()])
3    submit = SubmitField('Send validate code')
4
5
6class LoginSMSForm(FlaskForm):
7    validatacode = IntegerField('Enter validate code')
8    submit = SubmitField('Login')

新增两个路由函数,login_codesend和login_codeverify。分别处理两个表单的提交逻辑。 login_codesend函数,会像输入的手机号发送verify code,并把产生的code传给login_codeverify函数,用于比较。

代码语言:javascript
复制
 1@auth.route('/logincodesend/', methods=['GET', 'POST'])
 2def login_codesend():
 3    codeform = LoginSMSCodeForm()
 4    if codeform.validate_on_submit():
 5        num = codeform.phonenumber.data
 6        user = UserPhone.query.filter_by(phone=num).first()
 7        if user is None:
 8            user = UserPhone(phone=num)
 9            db.session.add(user)
10            db.session.commit()
11        code = generate_code()
12        decod_code = decoding_code(code)
13        sendsms(decod_code, '+86' + str(num))
14        flash('Have send a validate code to your phone')
15        return redirect(url_for('.login_codeverify', code=code, num=num))
16    return render_template('auth/logincodesend.html', form=codeform)

login_codeverify函数,比较拿到的verify code和用户输入的code,如果一样,则登陆成功。

代码语言:javascript
复制
 1@auth.route('/logincodeverify/<code>/<num>', methods=['GET', 'POST'])
 2def login_codeverify(code, num):
 3    form = LoginSMSForm()
 4    code = decoding_code(code)
 5    if form.validate_on_submit():
 6        if str(form.validatacode.data) == code:
 7            webuser = WebUser.query.filter_by(phone=num).first()
 8            if webuser is None:
 9                webuser = WebUser(username=num, phone=num, user_id=time.time(), confirmed=True)
10                db.session.add(webuser)
11                db.session.commit()
12            phoneuser = UserPhone.query.filter_by(phone=num).first()
13            if phoneuser:
14                phoneuser.user_id = webuser.user_id
15                db.session.add(phoneuser)
16                db.session.commit()
17                login_user(webuser)
18                return redirect(url_for('main.index'))
19        flash('Invalid verify code')
20        return redirect(url_for('.login_codeverify', code=code, num=num))
21    return render_template('auth/logincodeverify.html', form=form)

添加用户资料页

gravatar用户头像

使用gravatar,它可以把用户的Email和头像关联起来,快速生成用户头像图片,其中Email地址需要经过md5加密处理。 可以使用查询字符串的形式,在url中传入参数,来获取头像图片。 参数说明

参数名

说明

s

图片大小,单位为像素

r

图片级别,可选值有“g”,“pg”,“r”和“x”

d

没有注册Gavatar服务的用户使用的默认图片生成方式,例如“identicon”

fd

强制使用默认头像

URL例子: http://secure.gravatar.com/avatar/ffd5c7d7bfcc8605aaa2d259e2590112?s=128&d=identicon&r=g

添加生成头像方法

在WebUser类中,添加生成头像的方法函数

代码语言:javascript
复制
 1    def gravatar(self, size=100, default='identicon', rating='g'):
 2        if request.is_secure:
 3            url = 'https://secure.gravatar.com/avatar'
 4        else:
 5            url = 'http://secure.gravatar.com/avatar'
 6        email = self.email or 'test@luobo.com'
 7        hash = self.avatar_hash or hashlib.md5(
 8            email.lower().encode('utf-8')).hexdigest()
 9        avatar = '{url}/{hash}?s={size}&d={default}&r={rating}'.format(
10            url=url, hash=hash, size=size, default=default, rating=rating
11        )
12        return avatar
丰富用户资料字段

为WebUser新增三个字段,以丰富用户资料

代码语言:javascript
复制
1    nickname = db.Column(db.String(64))
2    about_me = db.Column(db.Text())
3    avatar_hash = db.Column(db.String(32))
添加路由函数

添加展示用户profile的函数,这里对使用GitHub登陆的用户做了判断,优先展示GitHub的头像和用户名

代码语言:javascript
复制
 1@main.route('/user/<username>', methods=['GET', 'POST'])
 2@login_required
 3def user(username):
 4    user = WebUser.query.filter_by(username=username).first()
 5    if user is None:
 6        abort(404)
 7    if 'userid' in session:
 8        thirduser = ThirdOAuth.query.filter_by(user_id=session['userid']).first()
 9        if thirduser:
10            response = github.get('user', access_token=thirduser.oauth_access_token)
11            avatar = response['avatar_url']
12            gituser = response['login']
13            return render_template('user.html', user=user, avatar=avatar, gituser=gituser)
14    return render_template('user.html', user=user, avatar=None, gituser=None)

编辑用户资料

定义表单,包括username,nickname和about_me,用于提供给用户做修改

代码语言:javascript
复制
1class EditProfileForm(FlaskForm):
2    username = StringField('Username', validators=[Length(0, 64)])
3    nickname = StringField('Nickname', validators=[Length(0, 64)])
4    about_me = TextAreaField('About me')
5    submit = SubmitField('Submit')

然后在路由函数中判断,如果username存在且不是当前用户时,不能修改username,如果修改的username是唯一,那么更新数据库。

代码语言:javascript
复制
 1@main.route('/edit-profile', methods=['GET', 'POST'])
 2@login_required
 3def edit_profile():
 4    form = EditProfileForm()
 5    if form.validate_on_submit():
 6        username = form.username.data
 7        if WebUser.query.filter_by(username=username).first() and username != current_user.username:
 8            flash('This username has been used')
 9            return redirect(url_for('main.edit_profile'))
10        current_user.username = form.username.data
11        current_user.nickname = form.nickname.data
12        current_user.about_me = form.about_me.data
13        db.session.add(current_user)
14        db.session.commit()
15        flash('Your profile has been updated')
16        return redirect(url_for('.user', username=current_user.username))
17    form.username.data = current_user.username
18    form.nickname.data = current_user.nickname
19    form.about_me.data = current_user.about_me
20    return render_template('edit_profile.html', form=form)

页面演示

我将完整的代码上传到GitHub上了,有兴趣的同学可以戳这里: https://github.com/zhouwei713/flask-webauth 另外还配置了一个演示web,地址为: https://luobodazahui.top/ 同时还创建了几个测试用户,可以来体验 普通用户1: user1@luobo.com/test1 普通用户2: user2@luobo.com/test2 管理员用户1: admin1@luobo.com/admin1 管理员用户2: admin2@luobo.com/admin2

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 萝卜大杂烩 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 知识树
  • 短信发送demo
    • 使用twilio发短信
      • 产生validate code
      • 集成短信功能到系统
      • 添加用户资料页
        • gravatar用户头像
          • 添加生成头像方法
            • 丰富用户资料字段
              • 添加路由函数
              • 编辑用户资料
              • 页面演示
              相关产品与服务
              短信
              腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档