8.6 如何限制未认证用户访问有权限网页

——————————前言——————————————

上节我们讲了注册时向用户发送确认邮件, 确认成功把用户的confirm属性值改为1, 默认为0.

本节我们来利用这个confirm值来做些文章, 让未确认的用户登录以后不能看到主页, 显示一个页面提醒用户未确认账户, 让用户登录邮箱确认账户, 或者是选择重新发送确认邮件。

——————————————————————————

一. 修改|-app/-auth/views.py

@auth.before_app_request

def before_request():

    if current_user.is_authenticated() \  #用户已登录且

        and not current_user.confirm \  #用户未认证且

        and request.endpoint[:5] != 'auth.' \  #请求端点不为auth蓝本定义的路由

        and request.endpoint != 'static':  #请求断点不为static

        return redirect(url_for('auth.unconfirmed'))  #重定向


@auth.route('/unconfirmed')

def unconfirmed():

    if current_user.is_anonymous or current_user.confirm:  #防止已用户重复访问该链接

        return redirect(url_for('main.index'))

    return render_template('auth/unconfirmed.html')  #返回未确认页面, 页面内容见标题二


@auth.route('/confirm')

@login_required

def resend_confirmation():  #重新发送确认邮件

    token = current_user.generate_token()

    send_mail(current_user.email, 'Confirm your account', 'auth/email/confirm', user=current_user, token=token)

    flash('a confirm email has been sent to your email.')

    return redirect(url_for('main.index'))


代码说明:

    第二章我们讲过请求钩子, before_request注册一个函数, 在所有请求之前运行, auth蓝本注册的请求钩子的作用域只在该蓝本定义的路由中有效, 如果想把作用域应用的程序全局, 就要使用before_app_request。

    这样before_request函数就会在所有请求之前运行, 该函数的作用是使未认证用户登录以后重定向到未认证提醒页面,所以要加上current_user.is_authenticated() 和not current_user.confirm这两个判断条件,。

    然后程序就会重定向到auth.unconfirmed, 可是浏览器在发送auth.unconfirmed请求以后, 还是会先运行before_request函数, 就会再次重定向, 陷入循环, 因此我们加上request.endpoint[:5] != 'auth.'(endpoint存储的是请求端点, 如主页的请求断点就是main.index,)这个条件,这样访问auth蓝本的路由就不会重定向了。

    auth.unconfirmed路由返回提醒页面, 提醒页面包括一链接, 指向auth.resend_confirmation, 重新发送认证邮件。

    点击链接后, 程序重新发送验证邮件, 用户登录邮箱进行确认即可。

二. 修改|-app/templates/auth/unconfirmed.html

{% extends 'base.html' %}
{% block title %}Flasky - Confirm your account{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Hello, {{ current_user }}</h1>
<div>
<h2>You have not confirmed your account yet.</h2>
<p>Before you can access this site you need to confirm your account.Check your inbox, you should have received an email with a confirmation link.</p>
<p>Need another confirmathion link? <a href="{{ url_for('auth.resend_confirmation')}}">Click here</a></p>

{% endblock %}

三. 效果演示与代码说明

本次用登录sherry用户的过程来讲解程序的执行过程:

可见sherry用户未进行验证, 我们用浏览器访问程序主页,before_app_request注册的函数会在每个请求之前运行, 但是里面的限制条件只有已登录的未验证用户才会重定向, 所以未登录之前我们不用考虑这个钩子, 程序直接显示主页, 点击右上角登录链接显示登录页面:

输入信息并点击提交按钮以后, 我们就要考虑钩子的作用了, 见处理登陆的视图函数:

@auth.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and user.verify_password(form.password.data):
            login_user(user, form.remember_me)
            return redirect(request.args.get('next') or url_for('main.index'))
        flash('Invalid username or password.')

    return render_template('auth/login.html', form=form)

  我们点击提交按钮以后执行if语句块, 经过密码验证以后代码会登录用户, 并且返回主页的重定向, 浏览器发出请求主页的url后, 先执行钩子函数, 此时用户已登录, 并且未验证, 访问的又不是端点又不是auth., 于是重定向到auth.unconfirmed; 

  浏览器再发出请求auth.unconfirmed的url, 因为钩子函数中的条件request.endpoint[:5] != 'auth.', 所以所有对auth蓝本定义的路由的请求都可以忽略钩子函数, 返回auth/unconfirmed.html提醒页面:

点击链接, 访问auth.resend_confirmation视图函数, 重新发送邮件;

发完之后提示flash消息, 并且重定向到主页, 因为钩子函数的原因, 重定向到auth.unconfirmed:

我们登录邮箱, 发现一封新邮件:

打开后:


发现验证链接, 点击链接, 访问auth.confirm视图函数, 进行用户的认证, 认证通过, 用户的confirm属性值变为1:

重定向到主页, 因为此时用户已经认证, 所以可以忽略钩子函数, 程序返回主页:



*演示过程的说明都是按照代码的执行顺序讲解的。

四. request.endpoint != 'static'

注释:钩子函数中的request.endpoint != 'static'表明, 请求的端点是static, 可以忽略钩子函数:

可能有人会问, 我们的路由都是由auth和main蓝本定义的, 哪有名为static的端点?

还记得第二章的url_map吗:

最后一个端点就是static, 举例来说, 我们访问127.0.0.1:5000/static/favicon.ico就会得到我们的静态文件favicon.ico。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值