这里我是根据两个项目的实际情况做的总结,方法一(来自项目一)的登录用的是用户名(字符串)和密码,前后端不分离,用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实现登陆:

 from flask_login import login_user, login_required, logout_user, current_user
from app.controls.auth.forms import LoginForm @auth.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm() # 账户 密码表单
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is not None and user.verify_password(form.password.data):
login_user(user, form.remember_me.data)
return redirect(request.args.get('next') or url_for('user_mgm.index'))
flash('用户名或密码错误')
form.username.data = ''
form.password.data = ''
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

 @api.route('/users', methods=['POST'])
def register():
# 一. 获取参数
# request.data
# get_data获取的是字符串数据, 不利于后续的参数解析.
# 如果要用,需要配合json.loads()转换为字典格式的数据
# req_data = request.get_data()
# print req_data.get('mobile') # get_json: 方便的获取JSON数据, 同时会自动转换为字典
req_json = request.get_json()
mobile = req_json.get('mobile')
sms_code = req_json.get('sms_code')
password = req_json.get('password') # 二. 校验参数
# 1. 完整性
if not all([mobile, sms_code, password]):
# resp = {
# 'errno': RET.PARAMERR,
# 'errmsg': '参数不全,请重新输入'
# }
# return jsonify(resp) # 建议以后使用这种写法, 简单一些
return jsonify(errno=RET.PARAMERR, errmsg='参数不全,请重新输入') # 2. 验证手机号 --> import re.match(r"1[3456789]\d{9}", value)
if not re.match(r"^1[3456789]\d{9}$", mobile):
return jsonify(errno=RET.PARAMERR, errmsg='手机号不正确, 请输入正确手机号') # 三. 逻辑处理
# 1. 从redis中获取数据对比
# 2. 判断用户是否注册过,没注册就创建并保存用户
# 3.(注册后直接登录)保存session # 1.1 从redis中获取数据
try:
real_sms_code = redis_store.get('sms_code_%s' % mobile)
except Exception as e:
# logging.error(e)
# app.logger.error() logger模块默认已经集成到了app中, 但是没有智能提示不好用
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg='redis读取失败') # 1.2 判断数据是否为None
if real_sms_code is None:
return jsonify(errno=RET.NODATA, errmsg='短信验证码过期') # 1.3 对比短信验证码
if real_sms_code != sms_code:
return jsonify(errno=RET.DATAERR, errmsg='短信验证码填写错误') # 1.4 删除短信验证码
# 这里的1.3和1.4,与之前的短信验证码的步骤刚好相反.
# 短信验证码:1. 发短信要钱 2. 短信验证码接收可能时间过长或丢失(用户体验会不好)
try:
redis_store.delete('sms_code_%s' % mobile)
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR, errmsg='redis删除失败') # 2. 判断用户是否注册过,没注册就创建并保存用户(密码保存,会在模型中做加密处理)
try:
user = User.query.filter_by(mobile=mobile).first()
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR, errmsg='mysql查询失败')
else:
if user is not None:
# 用户信息不是None, 说明已存在(已注册)
return jsonify(errno=RET.DATAEXIST, errmsg='用户手机号已经注册') # 用户没有注册过 --> 创建用户对象并保存
user = User(name=mobile, mobile=mobile) # pbkdf2:sha256:50000$ey5Pg8Ie$4fca7afb538b79c4d6c66a4c8c3cae23c192f02bfa97e8c51605d1fa6cd08773
user.password = password # 用户1 123456 + 盐值 salt itcast
# 用户2 123456 + 盐值 salt hello
# i1t2c3a4s5t6
# h1e2l3l4056
# 希望有一个属性, 传入密码之后, 可以自动处理密码加密,并赋值给password_hash属性
# user.password_hash = password try:
db.session.add(user)
db.session.commit()
except Exception as e:
# 还需要数据回滚
db.session.rollback()
logging.error(e)
return jsonify(errno=RET.DBERR, errmsg='mysql添加失败') # 3.(注册后直接登录)保存session
try:
session['user_id'] = user.id
session['user_name'] = mobile
session['mobile'] = mobile
except Exception as e:
logging.error(e)
return jsonify(errno=RET.SESSIONERR, errmsg='session设置失败') # 四. 返回数据
return jsonify(errno=RET.OK, errmsg='注册成功')

手写登录

2  登出核心: 清除session

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

手写登出

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

 def login_required(func):
@wraps
def decorated_view(*args, **kwargs):
user_id = session.get('user_id')
if user_id is not None:
g.user_id = user_id
return func(*args, **kwargs)
else:
return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
return decorated_view

重写login_required

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

flask 实现登录 登出 检查登录状态 的两种方法的总结的更多相关文章

  1. linux尝试登录失败后锁定用户账户的两种方法

    linux尝试登录失败后锁定用户账户的两种方法 更新时间:2017年06月23日 08:44:31   作者:Carey    我要评论   这篇文章主要给大家分享了linux尝试登录失败后锁定用户账 ...

  2. 用js写出光棒效应的两种方法与jquery的两中方法

    <script src="js/jQuery1.11.1.js" type="text/javascript"></script> &l ...

  3. ASP.NET Core 登录登出 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 登录登出 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 登录登出 上一章节我们总算完善了注册的功能,而且也添加了一个用户,现 ...

  4. SpringBoot登录登出切面开发

    阅读本文约“2.5分钟” 本文开发环境是SpringBoot2.X版本. 对于系统而言(这里多指管理系统或部分具备登录登出功能的系统),登录登出是一个类权限验证的过程,现在一般是以token进行校验, ...

  5. 两种方法实现Linux不活动用户登录超时后自动登出

    在平常的工作中,windows系统使用的比较多一些,身边的很多同事都会对自己的电脑进行一些个性化设置,比如离开一段时间后自动锁屏.自动关闭屏幕.自动注销当前登录等.在windows下可以这样操作,那么 ...

  6. Struts2学习第六课 实现登录登出功能

    关于Struts2请求的扩展名问题: 1).org.apache.struts2包下的default.properties中配置了struts2应用的一些常量 2).struts.action.ext ...

  7. ThinkPHP---案例1登录登出和添加部门

    配置文件分3类:系统配置文件,分组配置文件,应用配置文件 ①系统配置文件ThinkPHP/Conf/convention.php: ②分组 / 模块 /平台配置文件Home/Conf/config.p ...

  8. Django项目: 4.用户登录登出功能

    用户登录登出功能 一.功能需求分析 1. 登录退出功能分析 流程图 功能 登录页面 登录功能 退出功能 二.登录页面 1. 接口设计 接口说明 类目 说明 请求方法 GET url定义 /user/l ...

  9. jquery ajax常用的登录登出

    整理jquery+ajax的登录登出方法. //登录 var currentUserId = -1; $(function() { var timestamp = (new Date()).value ...

随机推荐

  1. ARM与FPGA通过spi通信设计1.spi基础知识

    SPI(Serial Peripheral Interface--串行外设接口)总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息.SPI总线可直接与各个厂家生产 ...

  2. iOS----------对单元格取余

    if (indexPath.row % 2 == 0) { cell.backgroundColor = [UIColor magentaColor]; }else{ cell.backgroundC ...

  3. 从 RAID 到 Hadoop Hdfs 『大数据存储的进化史』

    我们都知道现在大数据存储用的基本都是 Hadoop Hdfs ,但在 Hadoop 诞生之前,我们都是如何存储大量数据的呢?这次我们不聊技术架构什么的,而是从技术演化的角度来看看 Hadoop Hdf ...

  4. UDK命令

    UDK命令行参数与控制台命令都是大小写不敏感的 命令行  udn中文  udn英文 全词大小写匹配,正则表达式,在c++代码中搜索减号开头的命令行参数(如:-BENCHMARK.-onethread等 ...

  5. mssql 存储过程调用另一个存储过程中的结果的方法分享

    转自:http://www.maomao365.com/?p=6801 摘要: 下文将分享"一个存储过程"中如何调用"另一个存储过程的返回结果",并应用到自身的 ...

  6. rpc接口调用以太坊智能合约

    rpc接口调用以太坊智能合约 传送门: 柏链项目学院   在以太坊摸爬滚打有些日子了,也遇到了各种各样的问题.这几天主要研究了一下如何通过rpc接口编译.部署和调用合约.也遇到了一些困难和问题,下面将 ...

  7. Linux 用户关联命令

    在执行useradd命令创建用户时,它首先读取/etc/default/useradd文件的配置参数,然后通过这些参数来配置新创建的用户,如创建名为luser的用户. [root@rhl5 -]# u ...

  8. 什么是tomcat集群?

    什么是tomcat集群? 利用nginx对请求进行分流,将请求分配给不同的tomcat去处理,减少每个tomcat的负载量,提高服务器的响应速度. 目标 实现高性能负载均衡的tomcat集群. 工具 ...

  9. windows10 1903 64位系统

    近日,微软完成并开始推送Windows 10 2019年的第一个重大升级的预览版本,版本号是v1903,命名则是2019年5月更新版. 点击下载windows10

  10. SQLServer之视图简介

    视图定义 视图是一个虚拟表,其内容由查询定义. 同表一样,视图包含一系列带有名称的列和行数据. 视图在数据库中并不是以数据值存储集形式存在,除非是索引视图. 行和列数据来自由定义视图的查询所引用的表, ...