Files
secure-device-demo/springboot-server/src/main/java/com/secure/demo/config/WebConfig.java
TongTongStudio 586e5d9066 refactor(android): 改用设备签名拦截器认证,移除 challenge 往返
设备接口统一由 AuthInterceptor 注入 Device-Sig 头完成认证,删除手动 challenge 签名流程与 transport-key 接口,注册改用本地生成 ts:nonce 做 PoP 验签。
2026-08-27 08:43:02 +08:00

85 lines
3.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.secure.demo.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Web 层配置。
*
* <p>前后端分离后Web 用户端web-client与后端跨域通信需要放开 CORS。
* 但 <strong>不允许「任意来源 + 携带凭据」</strong>(那是严重风险:任何恶意站点都能借已登录
* 用户的凭据跨域调用受保护接口)。因此这里改为<strong>域名白名单</strong></p>
* <ul>
* <li>默认只允许本地开发域名localhost / 127.0.0.1 的常见端口);</li>
* <li>生产环境必须通过配置收紧为实际前端域名。</li>
* </ul>
*
* 配置方式(二选一,环境变量优先):
* <pre>
* # application.properties
* app.cors.allowed-origins=http://localhost:3000,https://app.example.com
* </pre>
* <pre>
* # 环境变量(可覆盖上面的配置)
* export APP_CORS_ALLOWED_ORIGINS="https://app.example.com,https://admin.example.com"
* </pre>
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
/** 本地开发默认白名单web-client 常驻端口) */
private static final String DEFAULT_ALLOWED_ORIGINS =
"http://localhost:3000,http://127.0.0.1:3000,"
+ "http://localhost:8080,http://127.0.0.1:8080,"
+ "http://localhost:5173,http://127.0.0.1:5173";
private final List<String> allowedOrigins;
private final DeviceAuthInterceptor deviceAuthInterceptor;
public WebConfig(
@Value("${app.cors.allowed-origins:}") String configuredOrigins,
@Value("${APP_CORS_ALLOWED_ORIGINS:}") String envOrigins,
DeviceAuthInterceptor deviceAuthInterceptor) {
String raw = (envOrigins != null && !envOrigins.isBlank()) ? envOrigins : configuredOrigins;
if (raw == null || raw.isBlank()) {
raw = DEFAULT_ALLOWED_ORIGINS;
}
this.allowedOrigins = Arrays.stream(raw.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
this.deviceAuthInterceptor = deviceAuthInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 设备签名认证拦截器:仅拦截需要设备认证的路径(/api/device/**、/api/photo/**
// 显式排除公开接口注册、登录、健康检查、CORS 预检)。
registry.addInterceptor(deviceAuthInterceptor)
.addPathPatterns("/api/device/**", "/api/photo/**")
.excludePathPatterns(
"/api/device/register", // 注册:设备未入库,用请求内公钥做 PoP 验签
"/api/photo/{photoId}/decrypt", // Web 用户端 Bearer 鉴权,非设备签名
"/api/photo/{photoId}/decrypt/stream"
);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
// 使用精确域名白名单(非 "*"。allowCredentials(true) 下 "*" 是非法且危险的。
.allowedOrigins(allowedOrigins.toArray(new String[0]))
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}