Flask Web开发入门(二)之Flask-Login使用

上一章我们介绍了使用Flask开发基本的Web应用,并使用session来进行基本的登录授权验证,接下来我们将使用Flask-Login来进行会话管理,来处理我们的“登入、登出”问题

Flask-Login provides user session management for Flask. It handles the common tasks of logging in, logging out, and remembering your users’ sessions over extended periods of time.

It will:

  • Store the active user’s ID in the session, and let you log them in and out easily.
  • Let you restrict views to logged-in (or logged-out) users.
  • Handle the normally-tricky “remember me” functionality.
  • Help protect your users’ sessions from being stolen by cookie thieves.
  • Possibly integrate with Flask-Principal or other authorization extensions later on.

However, it does not:

  • Impose a particular database or other storage method on you. You are entirely in charge of how the user is loaded.
  • Restrict you to using usernames and passwords, OpenIDs, or any other method of authenticating.
  • Handle permissions beyond “logged in or not.”
  • Handle user registration or account recovery.

还是上一章的Web应用,

  • 首先,通过LoginManager.init_app创建我们的应用,并通过login_view指定默认登录页,如果用户没有登录,则自动跳转到登录页:
app = Flask(__name__)
login_manager = LoginManager()
login_manager.init_app(app)

login_manager.login_view = 'login'
login_manager.login_message = 'please login!'
login_manager.session_protection = 'strong'
logger = flask_logger.get_logger(__name__)

flask_logger.get_logger是我们自定义的日志模块,后续介绍

  • 修改路由方法login
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        logger.debug("login post method")
        username = request.form['username']
        password = request.form['password']

        user = flask_db.get_user_engine(username)
        logger.debug('db user id is %s, detail is %s' % (user.username, user))

        next_url = request.args.get("next")
        logger.debug('next is %s' % next_url)

        if password == 'admin123' and username == user.username:
            # set login user
            user = User()
            user.id = username
            flask_login.login_user(user)

            resp = make_response(render_template('index.html', name=username))
            resp.set_cookie('username', username)
            if not is_safe_url(next_url):
                return abort(400)
            return redirect(next_url or url_for('index'))
        else:
            return abort(401)

    logger.debug("login get method")
    return render_template('login.html')

注意,用户通过验证之后,使用login_user方法让用户登录,flask_db.get_user_engine自定义获取数据库用户方法,后续介绍

当用户请求重定向到登入视图,它的请求字符串中会有一个 next 变量,其值为用户之前访问的页面,因此在我们完成验证之后,我们通过request.args.get(“next”)获取到用户之前访问的页面地址,并进行重定向,注意建议对此参数进行安全校验,避免重定向攻击

  • 使用login_required装饰器确保首页授权访问
@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
@flask_login.login_required
def index():
    logger.debug("index page, method is %s" % request.method)
    return render_template('index.html', name=flask_login.current_user.id)

  • 这里,稍微修改前端登录页面如下:

<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户登录title>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/styles.css') }}"/>
    <link rel="shortcut icon" href="{{ url_for('static', filename='images/wd_favicon.ico')}}"/>
head>
<body>
<div class="htmleaf-container">
    <div class="wrapper">
        <div class="container">
            <h1>Welcomeh1>
            
            <form class="form" method="post" action="">
                <input type="text" placeholder="Username" name="username" id="username">
                <input type="password" placeholder="Password" name="password" id="password">
                <button type="submit" id="login-button">Loginbutton>
            form>
        div>

        <ul class="bg-bubbles">
            <li>li>
            <li>li>
            <li>li>
            <li>li>
            <li>li>
            <li>li>
            <li>li>
            <li>li>
            <li>li>
            <li>li>
        ul>
    div>
div>

<script src="{{ url_for('static', filename='js/jquery-2.1.1.min.js') }} " type="text/javascript">script>

<div style="text-align:center;margin:50px 0; font:normal 14px/24px 'MicroSoft YaHei';color:#000000">
    <h1>管理后台h1>
div>
body>
html>
  • 默认首页index.html,使用部分使用Jinjia模板,部分使用Layui

<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>首页title>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='js/layui/css/layui.css') }}"/>
    <script src="{{ url_for('static', filename='js/jquery-2.1.1.min.js') }}" type="text/javascript">script>
    <script src="{{ url_for('static', filename='js/layui/layui.js') }}" type="text/javascript">script>
    <link rel="shortcut icon" href="{{ url_for('static', filename='images/favicon.ico')}}"/>
head>
<body>
<div style="width: 80%; float:left; margin: 10px 5px;font-family: Consolas;font-size: 20px;">
    {% if name %}
    Hello {{ name }}!
    {% else %}
    Hello World!
    {% endif %}
div>
<div style="float:right; width: 10%;margin: 10px 5px;font-family: Consolas;font-size: 20px;">
    <a href="#" onclick="javascript:logout();">logouta>
div>
<table class="layui-table">
    <colgroup>
        <col width="150">
        <col width="200">
        <col>
    colgroup>
    <thead>
    <tr>
        <th>昵称th>
        <th>加入时间th>
        <th>签名th>
    tr>
    thead>
    <tbody>
    <tr>
        <td>贤心td>
        <td>2016-11-29td>
        <td>layuitd>
    tr>
    <tr>
        <td>许闲心td>
        <td>2016-11-28td>
        <td>tabletd>
    tr>
    tbody>
table>
<script type="text/javascript">
    var logout = function () {
        window.location.href = '/logout';
    }
script>
body>
html>
  • 登出路由方法logout
@app.route('/logout')
@flask_login.login_required
def logout():
    # remove the username from the session if it's there
    logger.debug("logout page")
    flask_login.logout_user()
    return redirect(url_for('login'))

至此,我们完成了使用Flask-Login的登入、登出管理,接下来,我们介绍使用Request Loader定制登录

http://www.pythondoc.com/flask-login/

http://flask-login.readthedocs.io/en/latest/#login-example

源码参考:https://github.com/ypmc/flask-sqlalchemy-web

你可能感兴趣的:(架构,前端,Python,综合)