如何为私有 Web 应用程序实施最小访问控制?
How do I implement a minimal access control for a private Web App?
我正在开发 Web 应用程序 Python/Bottle 只有一个用户(我),运行 在我的 自己的 (https) 服务器 上。我想防止有人绊倒我的应用程序并滥用它,但同时我想 方便地使用它 来自我的 iPhone。每次输入 密码对我来说不是一个选项。
我在考虑是不是有一个复杂的 url 或向 url 添加一些标记并将此页面添加为书签。
这会提供我正在寻找的最低限度的安全性吗?还有更好的选择吗?
这似乎是一个小项目,也许您所建议的实际上可以保护您的 Web 应用程序,但这里是对您当前解决方案的一些解释。
您对“复杂 url”的建议听起来像是“通过隐蔽实现安全”:它不能解决您的 Web 应用程序没有安全机制的问题,但会使其更难访问您的应用程序的功能。通常,人们认为“通过模糊实现安全”是没有安全性的,因为在您的情况下,坚定的攻击者最终会找到一种访问复杂 URL 的方法。正如上面评论中提到的,也不鼓励在 URL 中添加 security/session 标记。
虽然,在您的用例中这些可能只是工作,但我想说两者都会在两种“攻击”场景中受到影响:
- 让您 phone 被盗,或无人看管,任何人都可以看到您的浏览历史记录
- Cross-domain Referer leakage
如果你能接受上面的风险,你就很好。
对我来说,使用 Bottle 实现最小登录功能并将 cookie 设置为“永不过期”似乎并不难。下面你会找到一个最小的例子(或者如果你愿意使用插件,你可以尝试Cork):
#!/usr/bin/env python
from bottle import route, run, request, redirect, response
import json
import os
import functools
import time
secret = os.urandom(32).hex()
USERNAME = "admin"
PASSWORD = "admin"
COOKIE_NAME = "session-cookie"
HTTPS = True
def verify_cookie() -> bool:
return request.get_cookie(COOKIE_NAME, secret=secret) == USERNAME
def verify_creds(username : str, password : str) -> bool:
return username == USERNAME and password == PASSWORD
def set_cookie(username : str):
in_ten_years_from_now = int(time.time()) + 10 * 365 * 24 * 60 * 60
response.set_cookie(COOKIE_NAME, username, secret=secret, expires = in_ten_years_from_now, secure=HTTPS, httponly=True)
def require_authorized(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if not verify_cookie():
redirect("/login")
return func(*args,**kwargs)
return wrapper
@route('/', method='GET')
@require_authorized
def index():
return f"Welcome, {request.get_cookie(COOKIE_NAME, secret=secret)}"
@route('/login', method=['GET','POST'])
def login():
if request.method == 'GET':
return "Welcome to the login page"
else:
username,password = request.forms.get("username"), request.forms.get("password")
if verify_creds(username,password):
set_cookie(username)
redirect("/")
else:
return "Invalid creds, pls retry"
if __name__ == "__main__":
run(host='localhost', port=8080)
我正在开发 Web 应用程序 Python/Bottle 只有一个用户(我),运行 在我的 自己的 (https) 服务器 上。我想防止有人绊倒我的应用程序并滥用它,但同时我想 方便地使用它 来自我的 iPhone。每次输入 密码对我来说不是一个选项。
我在考虑是不是有一个复杂的 url 或向 url 添加一些标记并将此页面添加为书签。
这会提供我正在寻找的最低限度的安全性吗?还有更好的选择吗?
这似乎是一个小项目,也许您所建议的实际上可以保护您的 Web 应用程序,但这里是对您当前解决方案的一些解释。
您对“复杂 url”的建议听起来像是“通过隐蔽实现安全”:它不能解决您的 Web 应用程序没有安全机制的问题,但会使其更难访问您的应用程序的功能。通常,人们认为“通过模糊实现安全”是没有安全性的,因为在您的情况下,坚定的攻击者最终会找到一种访问复杂 URL 的方法。正如上面评论中提到的,也不鼓励在 URL 中添加 security/session 标记。
虽然,在您的用例中这些可能只是工作,但我想说两者都会在两种“攻击”场景中受到影响:
- 让您 phone 被盗,或无人看管,任何人都可以看到您的浏览历史记录
- Cross-domain Referer leakage
如果你能接受上面的风险,你就很好。
对我来说,使用 Bottle 实现最小登录功能并将 cookie 设置为“永不过期”似乎并不难。下面你会找到一个最小的例子(或者如果你愿意使用插件,你可以尝试Cork):
#!/usr/bin/env python
from bottle import route, run, request, redirect, response
import json
import os
import functools
import time
secret = os.urandom(32).hex()
USERNAME = "admin"
PASSWORD = "admin"
COOKIE_NAME = "session-cookie"
HTTPS = True
def verify_cookie() -> bool:
return request.get_cookie(COOKIE_NAME, secret=secret) == USERNAME
def verify_creds(username : str, password : str) -> bool:
return username == USERNAME and password == PASSWORD
def set_cookie(username : str):
in_ten_years_from_now = int(time.time()) + 10 * 365 * 24 * 60 * 60
response.set_cookie(COOKIE_NAME, username, secret=secret, expires = in_ten_years_from_now, secure=HTTPS, httponly=True)
def require_authorized(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if not verify_cookie():
redirect("/login")
return func(*args,**kwargs)
return wrapper
@route('/', method='GET')
@require_authorized
def index():
return f"Welcome, {request.get_cookie(COOKIE_NAME, secret=secret)}"
@route('/login', method=['GET','POST'])
def login():
if request.method == 'GET':
return "Welcome to the login page"
else:
username,password = request.forms.get("username"), request.forms.get("password")
if verify_creds(username,password):
set_cookie(username)
redirect("/")
else:
return "Invalid creds, pls retry"
if __name__ == "__main__":
run(host='localhost', port=8080)