perf(security): make image proxy signature stable to enable client caching (#5835)

This commit is contained in:
InfinityPacer
2026-05-25 16:46:29 +08:00
committed by GitHub
parent d57deb1df1
commit 7ab1a668cb
2 changed files with 65 additions and 35 deletions

View File

@@ -27,7 +27,8 @@ class SecurityUtilsTest(TestCase):
signed_url = SecurityUtils.sign_url(url)
self.assertIn("#mp_exp=", signed_url)
self.assertIn("#mp_sig=", signed_url)
self.assertIn("mp_purpose=image-proxy", signed_url)
self.assertEqual(SecurityUtils.verify_signed_url(signed_url), url)
self.assertEqual(SecurityUtils.strip_url_signature(signed_url), url)
@@ -45,19 +46,50 @@ class SecurityUtilsTest(TestCase):
self.assertIsNone(SecurityUtils.verify_signed_url(tampered_url))
def test_signed_url_rejects_expired_signature(self):
def test_signed_url_is_deterministic_for_same_inputs(self):
"""
已过期签名不能继续放行私网图片代理请求。
相同 URL 与 RESOURCE_SECRET_KEY 多次签名结果必须完全一致,
保证浏览器 / Service Worker 缓存能稳定命中。
"""
with patch("app.utils.security.time.time", return_value=1000):
signed_url = SecurityUtils.sign_url(
"http://192.168.1.50:8096/Items/abc/Images/Primary",
expires_in=10,
)
url = "http://192.168.1.50:8096/Items/abc/Images/Primary"
with patch("app.utils.security.time.time", return_value=1011):
first = SecurityUtils.sign_url(url)
second = SecurityUtils.sign_url(url)
self.assertEqual(first, second)
self.assertEqual(SecurityUtils.verify_signed_url(first), url)
def test_signed_url_invalidated_after_secret_rotation(self):
"""
`RESOURCE_SECRET_KEY` 变更(进程重启或运维显式轮换)后旧签名必须作废,
作为签名长期有效模型的失效兜底。
"""
url = "http://192.168.1.50:8096/Items/abc/Images/Primary"
with patch(
"app.utils.security.settings.RESOURCE_SECRET_KEY",
"old-secret-value-aaaaaaaaaaaaaaaaaaaaaaaa",
):
signed_url = SecurityUtils.sign_url(url)
self.assertEqual(SecurityUtils.verify_signed_url(signed_url), url)
with patch(
"app.utils.security.settings.RESOURCE_SECRET_KEY",
"new-secret-value-bbbbbbbbbbbbbbbbbbbbbbbb",
):
self.assertIsNone(SecurityUtils.verify_signed_url(signed_url))
def test_signed_url_rejects_other_purpose(self):
"""
签名绑定 `purpose`,挪用到其它签名用途必须被拒绝。
"""
url = "http://192.168.1.50:8096/Items/abc/Images/Primary"
signed_url = SecurityUtils.sign_url(url)
self.assertIsNone(
SecurityUtils.verify_signed_url(signed_url, purpose="other-purpose")
)
def test_is_safe_url_keeps_default_allowlist_behavior(self):
"""
默认 URL 校验保持历史 allowlist 行为,避免影响非代理调用方。