Discuss / Python / 练习,结合SQLAlchemy、hmac 具有注册、验证、加密功能

练习,结合SQLAlchemy、hmac 具有注册、验证、加密功能

Topic source

Robottiii

#1 Created at ... [Delete] [Delete and Lock User]

app.py

from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from flask import Flask, request, render_template
import re, hmac, random

app = Flask(__name__)

engine = create_engine('mysql+mysqlconnector://root:password@localhost:3306/test')

# 创建user表
metadata = MetaData(engine)

user = Table('user', metadata,
             Column('id', Integer, primary_key=True, autoincrement=True),
             Column('username', String(16), nullable=False),
             Column('password', Text, nullable=False),
             Column('key', String(20), nullable=False)
             )

metadata.create_all(engine)  # 会检查有没有这个表 没的话再创建

Base = declarative_base()


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)  # autoincrement=True id自增长
    username = Column('username', String(16), nullable=False)
    password = Column('password', Text, nullable=False)
    key = Column('key', String(20), nullable=False)


DBSession = sessionmaker(bind=engine)


# 生成MD5口令
def hmac_md5(key, s):
    return hmac.new(key.encode('utf-8'), s.encode('utf-8'), 'MD5').hexdigest()


# 生成随机key 长度20
def get_key():
    return ''.join([chr(random.randint(48, 122)) for i in range(20)])


# 主页
@app.route('/', methods=['GET', 'POST'])
def home():
    return render_template('home.html')


# 注册页
@app.route('/register', methods=['GET'])
def get_register_page():
    return render_template('form.html', title='register', router='/register', message='')


# 用户名 密码格式验证正则
reg = r'^[a-zA-Z0-9_]{6,16}$'


# 注册接口
@app.route('/register', methods=['POST'])
def register():
    username, password = request.form['username'], request.form['password']
    if re.match(reg, username) and re.match(reg, password):  # 正则通过
        session = DBSession()
        if session.query(User).filter(User.username == username).first():  # 验证用户是否已注册 first返回最多一个结果没有返回None
            return render_template('form.html', title='register', router='/register',
                                   message='用户已注册')
        else:
            # 未注册情况
            key = get_key()  # 获取key
            password = hmac_md5(key, password + username)  # 生成MD5口令
            # 往数据库中添加一条记录
            new_user = User(username=username, password=password, key=key)
            session.add(new_user)
            session.commit()
            # 跳转至登录页
            return render_template('form.html', title='login', router='/login',
                                   message='')
        session.close()
    else:  # 正则未通过
        return render_template('form.html', title='register', router='/register',
                               message='格式错误,username、password应该由6到16位a-zA-Z0-9_组成')


# 登录页
@app.route('/login', methods=['GET'])
def get_login_page():
    return render_template('form.html', title='login', router='/login', message='')


@app.route('/login', methods=['POST'])
def login():
    username, password = request.form['username'], request.form['password']
    if re.match(reg, username) and re.match(reg, password):  # 正则通过
        session = DBSession()
        userinfo = session.query(User).filter(User.username == username).first()
        if userinfo:  # 判断用户是否存在
            password = hmac_md5(userinfo.key, password + username)  # 生成MD5口令
            if password == userinfo.password:  # 验证口令
                # 登录成功
                return render_template('login_ok.html', title='welcome', message='welcome to %s' % username)
            else:  # 验证口令失败
                return render_template('form.html', title='login', router='/login',
                                       message='用户名或密码错误')
        else:  # 不存在情况
            return render_template('form.html', title='login', router='/login',
                                   message='没有此用户')
        session.close()
    else:  # 正则未通过
        return render_template('form.html', title='login', router='/login',
                               message='格式错误,username、password应该由6到16位a-zA-Z0-9_组成')


if __name__ == '__main__':
    app.run()

home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Home</title>
</head>
<body>
    <h1>Home</h1>
</body>
</html>

form.html

<!DOCTYPE html>
<html lang="en" data-message="{{message}}">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
<form action="{{router}}" method="post">
    <p>
        <input name="username">
    </p>
    <p>
        <input name="password">
    </p>
    <p>
        <button type="submit">{{title}}</button>
    </p>
</form>
{% if message %}
    <script>
        let message = document.getElementsByTagName('html')[0].getAttribute('data-message')
        alert(message)
    </script>
{% endif %}
</body>
</html>

login_ok.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
    <h1>{{message}}</h1>
</body>
</html>

  • 1

Reply