这是 proper/secure 登录方式吗?
Is this a proper/secure way to log someone in?
好吧,我真的是编程新手(刚刚学会了如何建立数据库连接,write/read 今天从中学到了),我正在尝试制作一个允许用户登录的基本站点,并且在用户登录时有一些不同的页面。我决定使用 Flask,Flask-session,Sqlite3 进行尝试,基本上身份验证如下:用户使用表单登录,检查表单数据对照sqlite3数据库中的信息,如果正确,则将相应的值写入客户端cookie。这是一种可接受的登录方式吗?请原谅我的无知,但我真的是编程新手,我缺少一些关键术语来在这里寻找我自己的答案。我四处搜索,但无法确定这是否是一种可接受的方式 logins/out。
我的网站可以正常运行,但我不知道我是否真的在传统意义上登录或注销任何内容。还要注意一些路线被奇怪地破坏或隐藏,这只是因为我试图破坏事物以查看它们是如何工作的。要获取我的网站 运行,我没有包含模板:
from app.py import init_db
init_db()
python app.py
这是我的应用程序文件:
#importations
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, \
abort, render_template, flash, escape
from contextlib import closing
import sys
import datetime
from models import User
from formms import RegistrationForm, Login
import os
key1 = os.urandom(24)
#config
DATABASE = '/tmp/fitty1.db'
DEBUG = True
SECRET_KEY = key1
USERNAME = 'admin'
PASSWORD = 'default'
print key1
#Initialize the application
app = Flask(__name__)
app.config.from_object(__name__)
#login_manager = LoginManager()
#login_manager.init_app(app)
#Method to connect to database, use to open a connection on request, or from interactive python shell
def connect_db():
return sqlite3.connect(app.config['DATABASE'])
#Run this before application to initialize the DB
def init_db():
with closing(connect_db()) as db:
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
@app.teardown_request
def teardown_request(exception):
db = getattr(g, 'db', None)
if db is not None:
db.close()
@app.route('/')
def show_entries():
g.db = connect_db()
cur = g.db.execute('select title, text from entries order by id desc')
entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()]
return render_template('show_entries.html', entries=entries)
@app.route('/register', methods=['POST', 'GET'])
def register():
g.db = connect_db()
form = RegistrationForm(request.form)
if request.method == 'POST' and form.validate():
user = User(form.username.data, form.email.data, form.password.data)
g.db.execute('insert into users (username, email, password) values (?, ?, ?)',
[request.form['username'], request.form['email'], request.form['password']])
g.db.commit()
flash('Registered successfully')
return redirect(url_for('show_entries'))
return render_template('register.html', form=form)
@app.route('/account')
def account():
g.db = connect_db()
if not session.get('logged_in'):
abort(401)
if 'username' in session:
username = session['username']
c = g.db.execute("SELECT password from users where username = (?)", (username,))
passwc = c.fetchone()
c = g.db.execute("SELECT text from entries")
texty = c.fetchone()
return 'Your username is "%s", your password is "%s" and code %s' % (username, passwc[0], texty[0])
return 'You are not logged in'
@app.route('/add', methods=['POST'])
def add_entry():
g.db = connect_db()
if not session.get('logged_in'):
abort(401)
g.db.execute('insert into entries (title, text) values (?, ?)',
[request.form['title'], request.form['text']])
g.db.commit()
flash('New entry was successfully added')
return redirect(url_for('show_entries'))
@app.route('/login', methods=['GET', 'POST'])
def login():
g.db = connect_db()
error = None
form = Login(request.form)
user = User(form.username.data, form.email.data, form.password.data)
if request.method == 'POST':
c = g.db.execute("SELECT username from users where username = (?)", [form.username.data])
userexists = c.fetchone()
if userexists:
c = g.db.execute("SELECT password from users where password = (?)", [form.password.data])
passwcorrect = c.fetchone()
if passwcorrect:
session['username'] = form.username.data
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('account'))
else:
return 'password fail'
else:
return 'username fail'
return render_template('login.html', form=form)
@app.route('/logout')
def logout():
g.db = connect_db()
session.pop('logged_in', None)
flash('You were logged Out')
return redirect(url_for('show_entries'))
#Use build in server to run standalone application
if __name__ == '__main__':
app.run()
型号
import sqlite3
from flask import g
from flask.ext.login import LoginManager, login_required
class User():
def __init__(self,username,email,password,active=True):
self.username = username
self.email = email
self.password = password
self.active = active
def is_authenticated(self):
return True
#Return true if authenticated, provided credentials
def is_active(self):
return True
def is_anonymous(self):
return False
#return true if anon, actual user returns false
def __repr__(self):
return '<User %r>' % (self.email)
Schema.sql
drop table if exists entries;
create table entries (
id integer primary key autoincrement,
title text not null,
text text not null
);
drop table if exists users;
create table users (
id integer primary key autoincrement,
username text not null,
email text not null,
password text not null
);
这绝对是正确的做法。客户端 cookie 允许您唯一地识别用户。您只需要确保 cookie 足够随机,否则有人可能会欺骗它。
如果你给我的 cookie 是 uid=hailey
那会很糟糕,因为我可以轻松地将其编辑为 uid=ach1lles
并获得你的管理员权限。相反,您想做一些足够随机的事情,例如我的用户名和当前时间的 sha2 哈希的 base64 以及昨天 NYT 的标题或类似的疯狂事情。您可能希望将其添加为数据库 table,然后在我发出请求时检查它。
此外,不要将密码存储为文本,考虑像 bcrypt 这样的东西。 :)
您的第二个 SELECT 查询存在安全风险。只要知道任何一个用户的密码,就可以以任何用户身份登录。
假设您有以下用户(忽略密码是明文):
username | password
---------+---------
Jack | abc123
-------------------
Jill | def456
假设有人尝试使用 "Jack" 作为用户名和 "def456" 作为密码登录。
你的第一个SELECT
c = g.db.execute("SELECT username from users where username = (?)", [form.username.data])
将 return 打破杰克的记录。这会导致您执行第二个 SELECT
c = g.db.execute("SELECT password from users where password = (?)", [form.password.data])
这将打破 return 吉尔的记录。虽然这是不同的用户,但您只检查查询中的 return 记录,而不是与第一个查询相同的记录。即使输入错误的 Jack 密码,用户仍将以 Jack 身份登录。
理想情况下,您只想根据用户名执行一次查询,并将提交的密码与数据库中的密码进行比较。
c = g.db.execute("SELECT username, password from users where username = (?)", [form.username.data])
user = c.fetchone()
# don't forget to apply your hashing algorithm to form.password.data
if user and user[1] == form.password.data:
session['username'] = form.username.data
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('account'))
综上所述,我对 Flask-Login and Flask-Security 这样的库的推荐再多也不为过。身份验证很难正确。利用社区让它变得更容易。
好吧,我真的是编程新手(刚刚学会了如何建立数据库连接,write/read 今天从中学到了),我正在尝试制作一个允许用户登录的基本站点,并且在用户登录时有一些不同的页面。我决定使用 Flask,Flask-session,Sqlite3 进行尝试,基本上身份验证如下:用户使用表单登录,检查表单数据对照sqlite3数据库中的信息,如果正确,则将相应的值写入客户端cookie。这是一种可接受的登录方式吗?请原谅我的无知,但我真的是编程新手,我缺少一些关键术语来在这里寻找我自己的答案。我四处搜索,但无法确定这是否是一种可接受的方式 logins/out。
我的网站可以正常运行,但我不知道我是否真的在传统意义上登录或注销任何内容。还要注意一些路线被奇怪地破坏或隐藏,这只是因为我试图破坏事物以查看它们是如何工作的。要获取我的网站 运行,我没有包含模板:
from app.py import init_db
init_db()
python app.py
这是我的应用程序文件:
#importations
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, \
abort, render_template, flash, escape
from contextlib import closing
import sys
import datetime
from models import User
from formms import RegistrationForm, Login
import os
key1 = os.urandom(24)
#config
DATABASE = '/tmp/fitty1.db'
DEBUG = True
SECRET_KEY = key1
USERNAME = 'admin'
PASSWORD = 'default'
print key1
#Initialize the application
app = Flask(__name__)
app.config.from_object(__name__)
#login_manager = LoginManager()
#login_manager.init_app(app)
#Method to connect to database, use to open a connection on request, or from interactive python shell
def connect_db():
return sqlite3.connect(app.config['DATABASE'])
#Run this before application to initialize the DB
def init_db():
with closing(connect_db()) as db:
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
@app.teardown_request
def teardown_request(exception):
db = getattr(g, 'db', None)
if db is not None:
db.close()
@app.route('/')
def show_entries():
g.db = connect_db()
cur = g.db.execute('select title, text from entries order by id desc')
entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()]
return render_template('show_entries.html', entries=entries)
@app.route('/register', methods=['POST', 'GET'])
def register():
g.db = connect_db()
form = RegistrationForm(request.form)
if request.method == 'POST' and form.validate():
user = User(form.username.data, form.email.data, form.password.data)
g.db.execute('insert into users (username, email, password) values (?, ?, ?)',
[request.form['username'], request.form['email'], request.form['password']])
g.db.commit()
flash('Registered successfully')
return redirect(url_for('show_entries'))
return render_template('register.html', form=form)
@app.route('/account')
def account():
g.db = connect_db()
if not session.get('logged_in'):
abort(401)
if 'username' in session:
username = session['username']
c = g.db.execute("SELECT password from users where username = (?)", (username,))
passwc = c.fetchone()
c = g.db.execute("SELECT text from entries")
texty = c.fetchone()
return 'Your username is "%s", your password is "%s" and code %s' % (username, passwc[0], texty[0])
return 'You are not logged in'
@app.route('/add', methods=['POST'])
def add_entry():
g.db = connect_db()
if not session.get('logged_in'):
abort(401)
g.db.execute('insert into entries (title, text) values (?, ?)',
[request.form['title'], request.form['text']])
g.db.commit()
flash('New entry was successfully added')
return redirect(url_for('show_entries'))
@app.route('/login', methods=['GET', 'POST'])
def login():
g.db = connect_db()
error = None
form = Login(request.form)
user = User(form.username.data, form.email.data, form.password.data)
if request.method == 'POST':
c = g.db.execute("SELECT username from users where username = (?)", [form.username.data])
userexists = c.fetchone()
if userexists:
c = g.db.execute("SELECT password from users where password = (?)", [form.password.data])
passwcorrect = c.fetchone()
if passwcorrect:
session['username'] = form.username.data
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('account'))
else:
return 'password fail'
else:
return 'username fail'
return render_template('login.html', form=form)
@app.route('/logout')
def logout():
g.db = connect_db()
session.pop('logged_in', None)
flash('You were logged Out')
return redirect(url_for('show_entries'))
#Use build in server to run standalone application
if __name__ == '__main__':
app.run()
型号
import sqlite3
from flask import g
from flask.ext.login import LoginManager, login_required
class User():
def __init__(self,username,email,password,active=True):
self.username = username
self.email = email
self.password = password
self.active = active
def is_authenticated(self):
return True
#Return true if authenticated, provided credentials
def is_active(self):
return True
def is_anonymous(self):
return False
#return true if anon, actual user returns false
def __repr__(self):
return '<User %r>' % (self.email)
Schema.sql
drop table if exists entries;
create table entries (
id integer primary key autoincrement,
title text not null,
text text not null
);
drop table if exists users;
create table users (
id integer primary key autoincrement,
username text not null,
email text not null,
password text not null
);
这绝对是正确的做法。客户端 cookie 允许您唯一地识别用户。您只需要确保 cookie 足够随机,否则有人可能会欺骗它。
如果你给我的 cookie 是 uid=hailey
那会很糟糕,因为我可以轻松地将其编辑为 uid=ach1lles
并获得你的管理员权限。相反,您想做一些足够随机的事情,例如我的用户名和当前时间的 sha2 哈希的 base64 以及昨天 NYT 的标题或类似的疯狂事情。您可能希望将其添加为数据库 table,然后在我发出请求时检查它。
此外,不要将密码存储为文本,考虑像 bcrypt 这样的东西。 :)
您的第二个 SELECT 查询存在安全风险。只要知道任何一个用户的密码,就可以以任何用户身份登录。
假设您有以下用户(忽略密码是明文):
username | password
---------+---------
Jack | abc123
-------------------
Jill | def456
假设有人尝试使用 "Jack" 作为用户名和 "def456" 作为密码登录。
你的第一个SELECT
c = g.db.execute("SELECT username from users where username = (?)", [form.username.data])
将 return 打破杰克的记录。这会导致您执行第二个 SELECT
c = g.db.execute("SELECT password from users where password = (?)", [form.password.data])
这将打破 return 吉尔的记录。虽然这是不同的用户,但您只检查查询中的 return 记录,而不是与第一个查询相同的记录。即使输入错误的 Jack 密码,用户仍将以 Jack 身份登录。
理想情况下,您只想根据用户名执行一次查询,并将提交的密码与数据库中的密码进行比较。
c = g.db.execute("SELECT username, password from users where username = (?)", [form.username.data])
user = c.fetchone()
# don't forget to apply your hashing algorithm to form.password.data
if user and user[1] == form.password.data:
session['username'] = form.username.data
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('account'))
综上所述,我对 Flask-Login and Flask-Security 这样的库的推荐再多也不为过。身份验证很难正确。利用社区让它变得更容易。