场景:
web页面如果多人用同一账号同时登录操作,可能会导致数据等的混乱甚至出现故障。并且可能损害开发者的利益。为此,本篇文章就讲下如何实现同一账户同时仅能一个地方登录操作。
思路:
1. 用户登陆时生成token(uuid.uuid4(),保存到数据库并设定session。
2. 用户操作视图加一个装饰器,这个装饰器的功能就是验证session[“token”]和数据库里的token是否一至,不一致的话就返回登录页面,禁止操作
代码:
----app.py
----config.py
----templates (不展示)
----static (不展示)
config.py
import os
from datetime import timedelta
basedir = os.path.abspath(os.path.dirname(__file__))
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:passworld@localhost:3306/singlelogin?charset=utf8'
SQLALCHEMY_TRACK_MODIFICATIONS = False
PERMANENT_SESSION_LIFETIME=timedelta(hours=6)
app.py
from flask import Flask,jsonify,request,redirect,render_template,session
import os
from flask_sqlalchemy import SQLAlchemy
import hashlib
import uuid
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.secret_key = "your secret key"
app.config.from_object("config")
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
passwd = db.Column(db.String(128))
token = db.Column(db.String(128),default=None)
def __repr__(self):
return self.name
with app.app_context():
db.create_all()
def loginVaild(fun):
def inner(*args, **kwargs):
userid=session.get("login_id")
session_token=session.get("token")
userinfo=User.query.filter_by(id=userid).first()
if userinfo.token==session_token:
return fun(*args, **kwargs)
else:
return render_template("login.html")
return inner
def setPassword(password):
password += "the string you like"
md5 = hashlib.md5()
md5.update(password.encode())
result = md5.hexdigest()
return result
@app.route("/index",methods=["GET"])
@app.route("/",methods=["GET"])
@loginVaild
def index():
print(session)
return jsonify(msg="dddd")
@app.route("/login",methods=["GET","POST"])
def login():
if request.method == "POST":
user_name = request.form.get("user_name")
user_pwd = request.form.get("user_pwd")
if not user_pwd or not user_name:
data = "用户名和密码不能为空!"
return render_template("login.html", data=data, usr=user_name)
login_user = User.query.filter_by(name=user_name).first()
if not login_user:
data = "用户名不存在!"
return render_template("login.html", data=data, usr=user_name)
s_pwd = setPassword(user_pwd)
if s_pwd != login_user.passwd:
data = "密码错误!"
return render_template("login.html", data=data, usr=user_name)
session["login_name"] = user_name
session["login_id"] = login_user.id
new_token = str(uuid.uuid4())
session["token"]=new_token
login_user.token = new_token
db.session.commit()
return redirect("/index")
return render_template("login.html")
@app.route("/register",methods=["GET","POST"])
def refister():
if request.method == "GET":
return render_template("register.html")
else:
user_name = request.form.get("user_name")
if User.query.filter_by(name=user_name).first():
return jsonify(msg="用户名已存在!")
user_pwd = request.form.get("user_pwd")
user_pwd = setPassword(user_pwd)
user = User(name=user_name, passwd=user_pwd)
db.session.add(user)
db.session.commit()
return jsonify(msg="SUCCESS")
if __name__ == '__main__':
app.run(host="0.0.0.0",port=8080)