一. 使用 Werkzeug 实现密码散列.

generate_password_hash(password, method=pbkdf2:sha1, salt_length=8)

将原始密码作为输入, 以字符串形式输出密码散列值, 输出的值可保存在用户数据库中. method 和 salt_length 的默认值就能满足大多数需求.

check_password_hash(hash, password)

这个函数的参数是从数据库中取回的密码散列值和用户输入的密码. 返回值为 True, 表明密码正确.

示例代码 :

from werkzeug.security import generate_password_hash, check_password_hash

class User(db.Model):

    # ... 

    password_hash = db.Column(db.String(128))

    @property
    def password(self):         # 设置属性不可读.
        raise AttributeError("Password is not a readable attribute.")

    @password.setter
    def password(self, password):   # 写入密码
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):    # 认证密码
        return check_password_hash(self.password_hash, password)

二. 使用 Flask-Login 认证用户.

用户登录程序后, 他们的认证状态要被记录下来, 这样浏览不同的页面时, 才能记住这个状态.

Flask-Login 是专门用来管理用户认证系统中的认证状态, 并且不依赖特定的认证机制.

1. 安装

$ pip install flask-loging

2. 初始化

from flask_login import LoginManager

login_manager = LoginManager(app)
login_manager.session_protection = 'strong'
login_manager.login_view = 'auth.login'

session_protection : 属性可以设为 None, 'basic', 'strong' , 已提供不同的安全等级防止用户篡改会话.
strong : Flask-Login 会记录客户端IP地址和浏览器的用户代理信息, 如果发现异常就登出用户.

login_view : 设置登录页面的端点.

3. 使用方法

1) 模型实现

方法一 : 实现4个模型方法

使用 Flask-Login 扩展, 程序的 模型必须实现几个方法 :

Flask-Login 要求实现的用户方法

方法 说明
is_authenticated() 如果用户一登录, 返回 True, 否则返回 False
is_active() 如果允许用户登录, 返回 True, 否则返回 False. 如果要禁用账户, 可以返回 False
is_anonymous() 对普通用户必须返回 False
get_id() 必须返回用户的唯一标识符, 使用 Unicode 编码字符串

这四个方法可以在模型类中作为方法直接实现.

方法二 : UserMixin 类

Flask-Login 提供了一个 UserMixin 类, 其中包含以上方法的默认实现, 且能满足大多数需求.

示例代码 :

from flask_login import UserMixin

class User(UserMixin, db.Model):
    pass

回调函数 : 使用指定的标识符加载用户. 定义在用户模型中.

加载用户的回调函数, 接受已 Unicode 字符串形式表示的用户标识符. 如果能找到用户, 这个函数必须返回用户对象, 否则返回 None.

示例代码 :

from . import login_manager

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

2) 保护路由 : login_required 装饰器

为了保护路由只让认证用户访问, Flask-Login 提供了一个 login_required 装饰器.

示例代码 :

from flask_login import login_required

@app.route('/secret')
@login_required
def secret():
    return "Only authenticated users are allowed!"

3) 模板调用

Flask-Login 变量提供 current_user 变量, 且在视图函数和模板中自动可用, 该变量的值是当前登录的用户, 如果用户尚未登录, 则是一个匿名用户代理对象.

示例代码 :

# 视图函数中调用
from flask-login import current_user

@auth.route("/confirm/<token>")
@login_required
def confirm(token):
    if current_user.confirmed:
        return redirect(url_for("main.index"))
    if current_user.confirm(token):
        flash("You have confirmed you account. Thanks!")
    else:
        flash("You confirmation link is invalid or has expired.")
    return redirect(url_for("main.index"))

# 模板中调用
<ul class="nav navbar-nav navbar-right">
    {% if current_user.is_authenticated %}
    <li><a href="{{ url_for('auth.logout') }}">Sign Out</a></li>
    {% else %}
    <li><a href="{{ url_for('auth.login') }}">Sign In</a></li>
    {% endif %}
</ul>

4) 登入用户: login_user(user, BOOLEAN)

Flask-Login 提供 login_user() 函数, 在用户会话中把用户标记为已登录.

login_user() 函数的参数是要登录的用户, 以及可选的 "记住我" 布尔值, "记住我" 也可在表单中实现. 如果布尔值为 True, 那么 关闭浏览器后用户会话就会过期, 下次访问时要重新登录; 如果为 False, 那么会在用户浏览器中写入一个长期有效的 cookie, 使用这个 cookie 可以复现用户会话.

示例代码 :

from flask import render_template, redirect, request, url_for, flash
from flask_login import login_user

from . import auth
from ..models import User
from .forms import LoginForm

@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 is not None 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)

用户访问未授权的 URL 时, 会显示登录表单. Flask-Login 会把原地址保存在查询的 next 参数中, 这个参数可从 request.args 字典读取. 如果查询字符串没有 next 参数, 则重定向到首页.

5) 登出用户: logout_user()

Flask-Login 提供 logout_user() 函数, 删除并重设用户会话.

示例代码 :

from flask_login import logout_user, login_required

@auth.route("/logout")
@login_required
def logout():
    logout_user()
    flash("You have been logged out.")
    return redirect(url_for("main.index"))

三. 使用 itsdangerours 生成确认令牌

对于某些特定类型的程序, 有必要确认注册时用户提供的信息是否正确. 常见要求是能通过提供的调子邮件地址与用户取得联系.

In [1]: from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

In [2]: s = Serializer(app.config['SECRET_KEY'],expires_in=3600)

In [3]: token = s.dumps({'confirm':23})

In [4]: token
Out[4]: 'eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ4OTgyMDY4MiwiaWF0IjoxNDg5ODE3MDgyfQ.eyJjb25maXJtIjoyM30.Fg9uyyOMtJ7Mk_LhycSaJgI5tIkkK1tbfswTxZ7qaEk'

In [5]: data=s.loads(token)

In [6]: data
Out[6]: {'confirm': 23}

itsdangerous 提供多种生成令牌的方法. 其中 TimedJSONWebSignatureSerializer 类生成具有过期时间的 JSON web 签名(JSON Web Signatures, JWS). 这个类的构造函数接受的参数是一个密钥, 在 Flask 程序中可使用 SECRET_KEY 设置.

dumps() 方法为指定的数据生成一个加密签名, 然后在对数据和签名进行序列化, 生成令牌字符串. expires_in 参数设置令牌的过期时间, 单位为 秒.

loads() 用于解码令牌. 其唯一的参数是令牌字符串. 这个方法会检查签名和过期时间, 如果通过, 返回原始数据. 如果令牌不正确或过期, 抛出异常.

flask 扩展之 -- flask-login的更多相关文章

  1. Flask從入門到入土(二)——請求响应與Flask扩展

    ———————————————————————————————————————————————————————————— 一.程序和請求上下文 Flask從客戶端收到請求時,要讓視圖函數能訪問一些對象 ...

  2. Flask 扩展 表单

    pip install flask-wtf 一个简单的表单 from flask_wtf import Form from wtforms import StringField from wtform ...

  3. flask扩展系列之 - 访问速度限制

    flask-limiter 是一个对客户端的访问速率进行限制的flask扩展.可以自定义一些访问的(速度)限制条件来把那些触发限制的请求拒之门外.一般常用来进行对爬虫的限制. 下面就常见的用法,举了一 ...

  4. Inside Flask - flask 扩展加载过程

    Inside Flask - flask 扩展加载过程 flask 扩展(插件)通常是以 flask_<扩展名字> 为扩展的 python 包名,而使用时,可用 import flask. ...

  5. Flask 扩展 自定义扩展

    创建一个为视图访问加日志的扩展Flask-Logging,并从中了解到写Flask扩展的规范. 创建工程 先创建一个工程,目录结构如下: flask-logging/ ├ LICENSE # 授权说明 ...

  6. Flask从入门到精通之flask扩展

    Flask被设计成可扩展形式,因此并没有提供一些重要的功能,比如数据库和用户认证,所以开发者可以自由选择最适合程序的包,或者按需求自行开发.社区成员开发了大量不同用途的扩展,如果这还不能满足需求,你还 ...

  7. Flask扩展实现HTTP令牌token认证HTTPTokenAuth

    Token认证 在restful设计中,用户认证模式通常使用json web token,而不会使用传统的HTTP Basic认证(传入账号密码) token认证模式如下:在请求header中加入to ...

  8. 2.6、Flask扩展

    Flask 被设计为可扩展形式,故而没有提供一些重要的功能,例如数据库和用户认证,所以开发者可以自由选择最适合程序的包,或者按需求自行开发. 社区成员开发了大量不同用途的扩展,如果这还不能满足需求,你 ...

  9. Flask基础(13)-->Flask扩展Flask-Script

    Flask基础(12)-->Flask扩展Flask-Script # 前提是安装了Flask-Script # 联网运行 pip install flask-script from flask ...

  10. Flask扩展 -- flask-mail

    电子邮件是最常用的通信方式之一.虽然Python标准库中的smtplib包可用在Flask程序中发送电子邮件,但包装了smtplib的Flask-Mail扩展能更好的和Flask集成. 1.安装Fla ...

随机推荐

  1. 蓝桥杯-格子中输出-java

    /* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2016, 广州科技贸易职业学院信息工程系学生 * All rights reserved. * 文件名称: ...

  2. codeforces 803B Distances to Zero

    Distances to Zero 题目链接:http://codeforces.com/problemset/problem/803/B 题目大意: 给一串数字,求每个数字到离他最近数字0的距离.. ...

  3. sql注入基础(原理)

    一.注入的分类 按数据库分类:1.整形 2.字符型(需要考虑单引号闭合的问题,还有注释不必要的语句  #  ) eag:  id='admin'  id='admin and1=1'这样会报错  所以 ...

  4. 用php(session)实现留言板功能----2017-05-09

    要实现留言功能,发送者和接受者必不可少,其次就是留言时间留言内容. 要实现的功能: 1.登录者只能查看自己和所有人的信息,并能够给好友留言 2.留言板页面,好友采取下拉列表,当留言信息为空时,显示提示 ...

  5. 产品经理学Python:for循环、while循环

    Python中有两种循环,分别为:for循环和while循环. 1. for循环 for循环可以用来遍历某一对象(遍历:通俗点说,就是把这个循环中的第一个元素到最后一个元素依次访问一次).for循环的 ...

  6. 堆和栈(java内存)

    栈内存: 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为 ...

  7. js获取一组不重复的随机数的方法

    一.基本思路: 建立一个数组存放所有可以取到的值,每次从该数组中随机取走一个,放到新的数组中,直到完成. 二.实现方法 1.方法一: (1)创建一个数组arr,数组元素为所有可能出现元素的集合: (2 ...

  8. Oracle的substr函数

    一.Substr函数 substr(目标字符串,开始位置,长度) 注意:这里第三个参数:长度,相当于物理中的标量,没有方向性,所以不能用负值.虽然不报错,但是选择不出任何值出来(欢迎指正) 开始位置可 ...

  9. hdu698 Just a Hook 线段树-成段更新

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 很简单的一个线段树的题目,每次更新采用lazy思想,这里我采用了增加一个变量z,z不等于0时其绝 ...

  10. java jdk中安装证书的步骤

    需要注意的是:导入证书时,请确认导入的JDK为当前程序运行所用的JDK,且路径是jdk目录下的jre目录路径,非与jdk同级的jre目录 首先你可以把需要导入的证书放在keytool的同级目录下,然后 ...