python 中实现加密保存密码与加密登录

本文目的主要是想解决加密登录的问题,在注册时就把密码hash后保存在数据库中。加密的方案有很多,我要求不高,就选择了SHA256加盐。后端在接收到登录请求时在form中加了一个隐藏的salt,前端使用sha256.js先对密码做hash,加上salt做一次hash后提交。后端使用hashlib,将数据库中的已hash的密码值与salt相加再做一次hash,结果与前端提交上来的值做比较。

本文使用python+flask

后端代码摘段如下(数据库中的密码是经过hash了,将它加盐后再hash一次,就可以与前端送来的password判断了。盐值的产生是在响应‘login’时加入到form中):

import hashlib
from wtforms import StringField, PasswordField, SubmitField, HiddenField

class LoginForm():
    salt = HiddenField('salt')
    name = StringField('姓名', validators=[DataRequired()])
    password = PasswordField('密码', validators=[DataRequired()])
    submit = SubmitField('提交')


@app.route('/login', methods=['GET', 'POST'])
def login():
    def do_get(form):
        return render_template('login.html', form=form)

    def do_post(form):
        user = User.query.filter_by(name=form.name.data).first()
        if user is None or get_hash(user.password + form.salt.data) != form.password.data:	# 将数据库中password值加盐后hash,就可以与提交上来的form.password中的值做比较了。
            session['logined'] = False
            flash('帐号或密码错误,请重新登录')
            return render_template('login.html', form=form)
        else:
            flash('登录成功!')
            session['logined'] = True
            session['name'] = form.name.data
            return redirect(url_for('index'))

    login_form = LoginForm()
    if request.method == 'GET':
        login_form.salt.data = uuid.uuid4().hex	# 产生盐值
        return do_get(login_form)
    else:
        return do_post(login_form)


def get_hash(s):
    hash = hashlib.sha256()
    hash.update(s.encode('utf-8'))
    return hash.hexdigest()

前端regist.html(关键在后边的提交的script代码,将密码hash后再提交,这样子数据库中保存的密码是经过hash的,但未加盐。加盐这一步放在登录时使用。):

{% extends 'base.html' %}
{% block title %}注册 - {% endblock %}
{% block content %}
    {% for message in get_flashed_messages() %}
        <div class="alert alert-warning">
            <button class="close" data-dismiss="alert">&times;</button>
            {{ message }}
        </div>
    {% endfor %}
    <div class="col-md-12 text-center">
        <form class="form-horizontal" role="form" id="regform" action="./register" method="post">
            <div class="form-group">
                <div><h3>注册信息</h3></div><br>
                <label for="name">姓&nbsp &nbsp &nbsp &nbsp名</label>
                {{ form.name }}<br><br>
                <label for="password">密&nbsp &nbsp &nbsp &nbsp码</label>
                {{ form.password }}<br><br>
                <label for="password2">{{ form.password2.label }}</label>
                {{ form.password2 }}<br><br>
                <label for="phonenum">{{ form.phonenum.label }}</label>
                {{ form.phonenum }}<br><br>
                <label for="unit">{{ form.unit.label }}</label>
                {{ form.unit }}<br><br>
                <span class="col-md-2 col-md-offset-4 col-xs-6">
                    <input type="button" class="form-control btn btn-default" onclick="register()" value= "提交">
                </span>
                <span class="col-md-2 col-xs-6">
                    <input type="reset" class="form-control btn btn-default" value= "复位">
                </span>
            </div>
        </form>
    </div>
{% endblock %}
{% block script %}
    {{ super() }}
    <script type="text/javascript" src="../static/sha256.js"></script>
    <script>
        function register() {
            var regform = document.getElementById("regform");
            if (regform.password.value !=  regform.password2.value){
                alert("确认密码与密码不符合,请重新输入");
            }
            else{
                regform.password.value = sha256_digest(regform.password.value);	# 提交之前把password的值hash,这样子后端数据库中的password就是经过hash的密码
                regform.submit();
            }
        }
    </script>
{% endblock %}

前端的login.html(关键在后边的提交的script代码,将密码hash后,加盐再hash,然后再提交):

{% extends 'base.html' %}
{% block title %}登录 - {% endblock %}
{% block content %}
    {% for message in get_flashed_messages() %}
        <div class="alert alert-warning">
            <button class="close" data-dismiss="alert">&times;</button>
            {{ message }}
        </div>
    {% endfor %}
    <div class="col-md-12 text-center">
        <form id="login" class="form-horizontal" role="form" action="./login" method="post">
            <div class="form-group">
                <div><h3>用户登录</h3></div><br>
                <!--{{ form.hidden_tag() }}-->
                {{ form.salt }}
                <label for="name" class="control-label">{{ form.name.label }}</label>
                {{ form.name }}<br><br>
                <label for="password" class="control-label">{{ form.password.label }}</label>
                {{ form.password }}<br><br>
                <span class="col-md-2 col-md-offset-4 col-xs-6">
                    <input type="button" class="form-control btn-default" value="提交" onclick="login()">
                </span>
                <span class="col-md-2 col-xs-6">
                    <input type="reset" class="form-control btn-default" value="复位">
                </span>
            </div>
        </form>
    </div>
{% endblock %}
{% block script %}
    {{ super() }}
    <script type="text/javascript" src="../static/sha256.js"></script>
    <script>
        function login() {
            var loginform = document.getElementById("login");
            loginform.password.value = sha256_digest(sha256_digest(loginform.password.value)+loginform.salt.value);	# 登录时,要将密码先hash一次(此值就跟数据库中的值是一样的了),加盐后又hash。
            loginform.submit();
        }
    </script>
{% endblock %}
展开阅读全文

没有更多推荐了,返回首页