account_request_integrity.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package service
  2. import (
  3. infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
  4. "github.com/gin-gonic/gin"
  5. "log/slog"
  6. )
  7. const requestIntegrityModeKey = "request_integrity_mode"
  8. // Identity/TLS and request integrity are independent controls. Existing mode1
  9. // supplies the default; an administrator can explicitly turn the check off.
  10. func (a *Account) RequestIntegrityMode() string {
  11. if a == nil || a.Platform != PlatformOpenAI {
  12. return "off"
  13. }
  14. if mode, ok := a.Extra[requestIntegrityModeKey].(string); ok {
  15. switch mode {
  16. case "off", "observe", "enforce":
  17. return mode
  18. }
  19. }
  20. if isMode1ProtectionEnabled(a) {
  21. return "enforce"
  22. }
  23. if isOpenAIOAuthLike(a) && a.AntiDegradationEnabled() {
  24. return "observe"
  25. }
  26. return "off"
  27. }
  28. func validateRequestIntegrityExtra(extra map[string]any) error {
  29. value, present := extra[requestIntegrityModeKey]
  30. if !present || value == nil {
  31. return nil
  32. }
  33. if mode, ok := value.(string); ok && (mode == "off" || mode == "observe" || mode == "enforce") {
  34. return nil
  35. }
  36. return infraerrors.BadRequest("REQUEST_INTEGRITY_INVALID", "请求完整性模式必须为关闭、仅观察或严格拦截")
  37. }
  38. func checkAccountRequestIntegrity(c *gin.Context, a *Account, original, forwarded []byte) error {
  39. mode := a.RequestIntegrityMode()
  40. if mode == "off" {
  41. return nil
  42. }
  43. err := validateMode1RequestIntegrityForAccount(a, original, forwarded)
  44. if err == nil {
  45. return nil
  46. }
  47. if c != nil {
  48. c.Set("request_integrity_difference", true)
  49. }
  50. // Error text is produced by the validator and contains field names only;
  51. // never record request bodies, credentials or conversation content here.
  52. slog.Warn("account_request_integrity_difference", "account_id", a.ID, "mode", mode, "error", err.Error())
  53. if mode == "enforce" {
  54. return err
  55. }
  56. return nil
  57. }