zoukankan      html  css  js  c++  java
  • flask 实现登录 登出 检查登录状态 的两种方法的总结

    这里我是根据两个项目的实际情况做的总结,方法一(来自项目一)的登录用的是用户名(字符串)和密码,前后端不分离,用form表单传递数据;方法二用的是手机号和密码登录,前后端分离,以json格式传递数据,所以对登录数据的验证是不同的

    方法一(利用插件 简单方便):

    利用插件 flask_login 的 login_user, login_required, logout_user, current_user方法来实现用户的登入  检查登录  登出  获取当前登录用户。

    首先 在view.py文件中做好导入工作:

      form flask_login import login_user, login_required,  logout_user, current_user

    1 利用login_user实现登陆:

     1 from flask_login import login_user, login_required, logout_user, current_user
     2 from app.controls.auth.forms import LoginForm
     3 
     4 @auth.route('/login', methods=['GET', 'POST'])
     5 def login():
     6     form = LoginForm() # 账户 密码表单
     7     if form.validate_on_submit():
     8         user = User.query.filter_by(username=form.username.data).first()
     9         if user is not None and user.verify_password(form.password.data):
    10             login_user(user, form.remember_me.data)
    11             return redirect(request.args.get('next') or url_for('user_mgm.index'))
    12         flash('用户名或密码错误')
    13         form.username.data = ''
    14         form.password.data = ''
    15     return render_template('/auth/login.html', form=form)
    login

    2 利用logout_user实现登出:

    @auth.route('/logout')
    @login_required
    def logout():
        # 直接调用logout_user函数退出,里面实质封装了对session信息的清除
        logout_user()
        return redirect(url_for('auth.login'))
    logout

    3 直接利用login_required装饰器检查登录状态:

    @auth.route('/changepwd', methods=['GET', 'POST'])
    @login_required  # 检查登录状态  只有通过验证才能更改密码
    def changepwd():
        form = ChangePwdForm()
        if form.validate_on_submit():
            if current_user.verify_password(form.oldpassword.data):
                current_user.password = form.newpassword.data
                db.session.add(current_user)
                db.session.commit()
                flash('密码修改成功!')
                return redirect(url_for('auth.login'))
            flash('原密码错误,请再次输入')
            form.oldpassword.data = ''
            form.newpassword.data = ''
            form.confirmedpassword.data = ''
        return render_template('auth/changepwd.html', name=current_user.name, grade=current_user.grade, form=form)
    login_required

    4 实现了1中的login_user(user, form.remember_me.data)方法,就可以在其他视图函数中直接通过current_user.name, current_user.grade来获取当前用户的属性,即current_user就代表当前的登录用户对象,它是通过login_user方法实现的。

    方法二(手写  模仿插件中的原理)

    1  登录核心内容: (1)验证用户输入的账号(手机号)和密码与数据库中的一致性  (2)通过验证,把用户数据保存到session

      1 @api.route('/users', methods=['POST'])
      2 def register():
      3     # 一. 获取参数
      4     # request.data
      5     # get_data获取的是字符串数据, 不利于后续的参数解析.
      6     # 如果要用,需要配合json.loads()转换为字典格式的数据
      7     # req_data = request.get_data()
      8     # print req_data.get('mobile')
      9 
     10     # get_json: 方便的获取JSON数据, 同时会自动转换为字典
     11     req_json = request.get_json()
     12     mobile = req_json.get('mobile')
     13     sms_code = req_json.get('sms_code')
     14     password = req_json.get('password')
     15 
     16     # 二. 校验参数
     17     # 1. 完整性
     18     if not all([mobile, sms_code, password]):
     19         # resp = {
     20         #     'errno': RET.PARAMERR,
     21         #     'errmsg': '参数不全,请重新输入'
     22         # }
     23         # return jsonify(resp)
     24 
     25         # 建议以后使用这种写法, 简单一些
     26         return jsonify(errno=RET.PARAMERR, errmsg='参数不全,请重新输入')
     27 
     28     # 2. 验证手机号 --> import re.match(r"1[3456789]d{9}", value)
     29     if not re.match(r"^1[3456789]d{9}$", mobile):
     30         return jsonify(errno=RET.PARAMERR, errmsg='手机号不正确, 请输入正确手机号')
     31 
     32     # 三. 逻辑处理
     33     # 1. 从redis中获取数据对比
     34     # 2. 判断用户是否注册过,没注册就创建并保存用户
     35     # 3.(注册后直接登录)保存session
     36 
     37     # 1.1 从redis中获取数据
     38     try:
     39         real_sms_code = redis_store.get('sms_code_%s' % mobile)
     40     except Exception as e:
     41         # logging.error(e)
     42         # app.logger.error() logger模块默认已经集成到了app中, 但是没有智能提示不好用
     43         current_app.logger.error(e)
     44         return jsonify(errno=RET.DBERR, errmsg='redis读取失败')
     45 
     46     # 1.2 判断数据是否为None
     47     if real_sms_code is None:
     48         return jsonify(errno=RET.NODATA, errmsg='短信验证码过期')
     49 
     50     # 1.3 对比短信验证码
     51     if real_sms_code != sms_code:
     52         return jsonify(errno=RET.DATAERR, errmsg='短信验证码填写错误')
     53 
     54     # 1.4 删除短信验证码
     55     # 这里的1.3和1.4,与之前的短信验证码的步骤刚好相反.
     56     # 短信验证码:1. 发短信要钱 2. 短信验证码接收可能时间过长或丢失(用户体验会不好)
     57     try:
     58         redis_store.delete('sms_code_%s' % mobile)
     59     except Exception as e:
     60         logging.error(e)
     61         return jsonify(errno=RET.DBERR, errmsg='redis删除失败')
     62 
     63     # 2. 判断用户是否注册过,没注册就创建并保存用户(密码保存,会在模型中做加密处理)
     64     try:
     65         user = User.query.filter_by(mobile=mobile).first()
     66     except Exception as e:
     67         logging.error(e)
     68         return jsonify(errno=RET.DBERR, errmsg='mysql查询失败')
     69     else:
     70         if user is not None:
     71             # 用户信息不是None, 说明已存在(已注册)
     72             return jsonify(errno=RET.DATAEXIST, errmsg='用户手机号已经注册')
     73 
     74         # 用户没有注册过 --> 创建用户对象并保存
     75         user = User(name=mobile, mobile=mobile)
     76 
     77         # pbkdf2:sha256:50000$ey5Pg8Ie$4fca7afb538b79c4d6c66a4c8c3cae23c192f02bfa97e8c51605d1fa6cd08773
     78         user.password = password
     79 
     80         # 用户1  123456 + 盐值 salt itcast
     81         # 用户2  123456 + 盐值 salt hello
     82         # i1t2c3a4s5t6
     83         # h1e2l3l4056
     84         # 希望有一个属性, 传入密码之后, 可以自动处理密码加密,并赋值给password_hash属性
     85         # user.password_hash = password
     86 
     87         try:
     88             db.session.add(user)
     89             db.session.commit()
     90         except Exception as e:
     91             # 还需要数据回滚
     92             db.session.rollback()
     93             logging.error(e)
     94             return jsonify(errno=RET.DBERR, errmsg='mysql添加失败')
     95 
     96     # 3.(注册后直接登录)保存session
     97     try:
     98         session['user_id'] = user.id
     99         session['user_name'] = mobile
    100         session['mobile'] = mobile
    101     except Exception as e:
    102         logging.error(e)
    103         return jsonify(errno=RET.SESSIONERR, errmsg='session设置失败')
    104 
    105     # 四. 返回数据
    106     return jsonify(errno=RET.OK, errmsg='注册成功')
    手写登录

    2  登出核心: 清除session

     1 @api.route("/sessions", methods=["DELETE"])
     2 @login_required
     3 def logout():
     4     """登出"""
     5     # 清除session数据, csrf_token需要保留.
     6     csrf_token = session['csrf_token']
     7     session.clear()
     8     session['csrf_token'] = csrf_token
     9 
    10     # 删除session的方式:3种
    11     # 1.session.pop()  2. 和Django所学相同  3. session.clear()全部删除
    12 
    13     return jsonify(errno=RET.OK, errmsg="OK")
    手写登出

    3 重写login_required装饰器检查登录状态,并把current_user的功能放到应用上下文g变量中供其他视图函数使用

     1 def login_required(func):
     2     @wraps
     3     def decorated_view(*args, **kwargs):
     4         user_id = session.get('user_id')
     5         if user_id is not None:
     6             g.user_id = user_id
     7             return func(*args, **kwargs)
     8         else:
     9             return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    10     return decorated_view
    重写login_required

    4 获取当前用户的功能封装在重写后的login_required中的g变量里,在其他视图函数中可以直接调用g.user_id获取当前登录用户的id

  • 相关阅读:
    IOS中的几种锁(转)
    IOS 主要框架 介绍
    码率bitrate,帧率frame rate,分辨率 (转)
    jupyter notebook 更换主题的方法
    谷歌刚发布的求梯度的工具包-Tangent
    吴恩达深度学习第1课第4周-任意层人工神经网络(Artificial Neural Network,即ANN)(向量化)手写推导过程(我觉得已经很详细了)
    女儿开始bababababa的发声了
    GrideSearchCV 优化算法参数
    修改博客园模板
    Printer for Me
  • 原文地址:https://www.cnblogs.com/We612/p/10401299.html
Copyright © 2011-2022 走看看