我在站点上实现授权,不使用表单,以免将密码发送到服务器。
登录.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Авторизация</title>
<link rel="stylesheet" href="../static/css/login.css">
<script type="text/javascript" src="../static/js/crypto-js.min.js"></script>
<script type="text/javascript" src="../static/js/login.js"></script>
</head>
<body>
<div class="container">
<div class="block">
<p id="autorization">Вход</p>
<div class="form">
<p><label>Логин<br><input type="text" id="username"></label></p>
<p><label>Пароль<br><input type="password" id="password"></label></p>
<p><label><input type="checkbox" id="remember">Запомнить меня</label></p>
<p><button id="submit">Отправить</button></p>
{% for category, message in get_flashed_messages(with_categories=True) %}
{% if category == 'error' %}
<p class="error-msg">{{ message }}</p>
{% endif %}
{% endfor %}
</div>
</div>
</div>
</body>
</html>
单击“提交”按钮时,将执行 onsubmit 方法。
登录.js:
window.onload = function() {
let submit = document.querySelector('button#submit');
submit.addEventListener('click', onsubmit)
};
function onsubmit() {
let username = document.querySelector('input#username').value;
let xhr = new XMLHttpRequest();
let send = JSON.stringify({'username': username});
xhr.open('POST', '/get-password-data', true);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.send(send);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
let data = JSON.parse(xhr.responseText);
if ('salt' in data && 'hash' in data) {
let password = document.querySelector('input#password').value;
let remember = document.querySelector('input#remember').value === 'on';
let hash = CryptoJS.PBKDF2(password, data.salt,
{keySize: 512/32, hasher: CryptoJS.algo.SHA512, iterations: 10000});
let xhr = new XMLHttpRequest();
let send = JSON.stringify({
'username': username,
'hash': hash.toString(),
'remember': remember
});
xhr.open('POST', '/login/', true);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.send(send);
xhr.onreadystatechange = function() {
console.log(xhr.readyState, xhr.responseText)
}
}
}
}
}
整个事情由 Flask 应用程序处理。
身份验证/views.py
@auth.route('/get-password-data', methods=['POST'])
def get_password_data():
data = request.get_json() # {'username': username}
username = data['username']
user = db.session.query(User).filter(User.username == username).first()
if user:
response = {
'salt': user.password_salt,
'hash': user.password_hash
}
return json.dumps(response), 200, {'ContentType': 'application/json'}
return (json.dumps({'message': 'No user'}), 200,
{'ContentType': 'application/json'})
@auth.route('/login/', methods=['POST', 'GET'])
def login():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
if request.method == 'POST':
# data == {'username': str, 'hash': str, 'remember': bool}
data = request.get_json()
user = db.session.query(User).filter(
User.username == data['username']).first()
if user and user.password_hash == data['hash']:
login_user(user, remember=data['remember'])
return redirect(url_for('main.index'))
flash(u'Неверный логин/пароль', 'error')
return redirect(url_for('auth.login'))
return render_template('login.html')
当用户输入错误的密码时,应该会重定向到 /login/ + 显示错误消息(请参阅模板中的消息循环)。如果用户输入了正确的密码,那么应该会重定向到 main.index ('/') 页面。
这没有发生。那些。输入正确密码时,页面不会转到'/',但用户被认为是授权的,因为。如果您自己重新启动页面,/login/ 将重定向到'/'(这是由于登录功能开头的条件)。好吧,如果您输入了错误的密码,也不会发生任何事情。但是,如果您显示服务器对 POST 请求 /login/ 的响应,您可以看到返回应该发生重定向的页面。
以前,当我使用授权表单时,一切正常,而“/login/”处理程序看起来像这样:
class LoginForm(FlaskForm):
username = StringField("Username", validators=[DataRequired()])
password = StringField("Password", validators=[DataRequired()])
remember = BooleanField("Remember Me")
submit = SubmitField()
@auth.route('/login/', methods=['POST', 'GET'])
def login():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = LoginForm()
if form.validate_on_submit():
user = db.session.query(User).filter(
User.username == form.username.data).first()
if user and user.check_password(form.password.data):
login_user(user, remember=form.remember.data)
return redirect(url_for('main.index'))
flash(u'Неверный логин/пароль', 'error')
return redirect(url_for('auth.login'))
return render_template('login.html', form=form)
问:为什么重定向不起作用?
您需要使用 JS 进行重定向。
服务器向转换请求返回一个 url。在 JS 中调用
window.location.href = url;。