fix(security): 安全加固 — analytics 权限校验 + HSTS/CSP 安全头 + SSE no-cache + SQL 参数化
- analytics batch() 添加 require_permission + 事件数上限 100 - main.rs 添加 HSTS/Content-Security-Policy/Permissions-Policy 安全头 - sse_handler SSE 响应添加 Cache-Control: no-store 防 token 泄漏 - action_inbox_service SQL 查询改为参数化,防注入 - wechat_handler 日志脱敏,不打印 appid/secret 长度 - dynamic_table sanitize_identifier 添加 63 字节限制
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashSet;
|
||||
use std::convert::Infallible;
|
||||
|
||||
use axum::extract::{Extension, Query};
|
||||
use axum::http::HeaderMap;
|
||||
use axum::http::{HeaderMap, HeaderValue, header};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::response::sse::{Event, KeepAlive, Sse};
|
||||
use futures::stream::Stream;
|
||||
use sea_orm::ConnectionTrait;
|
||||
@@ -13,6 +13,23 @@ use uuid::Uuid;
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::types::TenantContext;
|
||||
|
||||
/// 包装 SSE 响应,添加 Cache-Control: no-store 头
|
||||
pub struct NoCacheSse<S>(Sse<S>);
|
||||
|
||||
impl<S> IntoResponse for NoCacheSse<S>
|
||||
where
|
||||
S: Stream<Item = Result<Event, std::convert::Infallible>> + Send + 'static,
|
||||
{
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
let mut response = self.0.into_response();
|
||||
response.headers_mut().insert(
|
||||
header::CACHE_CONTROL,
|
||||
HeaderValue::from_static("no-store, no-cache, must-revalidate"),
|
||||
);
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
use crate::message_state::MessageState;
|
||||
|
||||
/// SSE 查询参数
|
||||
@@ -38,7 +55,7 @@ pub async fn message_stream(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
headers: HeaderMap,
|
||||
Query(query): Query<SseQuery>,
|
||||
) -> Result<Sse<impl Stream<Item = Result<Event, Infallible>>>, AppError> {
|
||||
) -> Result<NoCacheSse<impl Stream<Item = Result<Event, std::convert::Infallible>>>, AppError> {
|
||||
let user_id = ctx.user_id;
|
||||
let tenant_id = ctx.tenant_id;
|
||||
|
||||
@@ -165,10 +182,12 @@ pub async fn message_stream(
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Sse::new(sse_stream).keep_alive(
|
||||
KeepAlive::new()
|
||||
.interval(std::time::Duration::from_secs(30))
|
||||
.text("ping"),
|
||||
Ok(NoCacheSse(
|
||||
Sse::new(sse_stream).keep_alive(
|
||||
KeepAlive::new()
|
||||
.interval(std::time::Duration::from_secs(30))
|
||||
.text("ping"),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user