如何为私有 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 标记。

虽然,在您的用例中这些可能只是工作,但我想说两者都会在两种“攻击”场景中受到影响:

  1. 让您 phone 被盗,或无人看管,任何人都可以看到您的浏览历史记录
  2. 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)