本文最后更新于:2025年2月18日 下午
CSP
违规报告接口示例
Maven依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>2.0.51</version> </dependency>
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.26</version> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
|
前端
(可以在服务器端设置此请求头)而不是<meta>
标签
1
| Content-Security-Policy: default-src 'self'; script-src 'self'; report-uri /csp-violation-report-endpoint
|
例如Spring
后端项目:
1 2 3 4 5 6 7
| @GetMapping() public String index(HttpServletResponse response) { response.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self'; report-uri /csp-violation-report-endpoint");
return "index"; }
|
后端接收模型
CspViolationReportWrapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data;
public class CspViolationReportWrapper {
@JsonProperty("csp-report") private CspViolationReport cspReport;
public CspViolationReport getCspReport() { return cspReport; }
public void setCspReport(CspViolationReport cspReport) { this.cspReport = cspReport; }
@Data public static class CspViolationReport { private String referrer;
@JsonProperty("status-code") private int statusCode;
private String disposition; private String scriptSample;
@JsonProperty("violated-directive") private String violatedDirective;
@JsonProperty("original-policy") private String originalPolicy;
@JsonProperty("source-file") private String sourceFile;
@JsonProperty("document-uri") private String documentUri;
@JsonProperty("line-number") private int lineNumber;
@JsonProperty("effective-directive") private String effectiveDirective;
@JsonProperty("blocked-uri") private String blockedUri;
} }
|
实体类
CspViolationReport.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| import lombok.Data;
@Data public class CspViolationReport {
private Long id;
private String documentUri;
private String referrer;
private String violatedDirective;
private String effectiveDirective;
private String sourceFile;
private int lineNumber;
private int columnNumber;
private String statusCode;
private Long timestamp; }
|
转换器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.msrl.zhibo.thirdparty.demo;
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.stereotype.Component;
import java.io.IOException; import java.util.Collections; import java.util.List;
@Component public class CspReportMessageConverter extends MappingJackson2HttpMessageConverter {
public CspReportMessageConverter(ObjectMapper objectMapper) { super(objectMapper); setSupportedMediaTypes(Collections.singletonList(MediaType.valueOf("application/csp-report"))); } }
|
配置类
1 2 3 4 5 6 7 8 9 10 11 12
| @Configuration @RequiredArgsConstructor public class WebMvcConfig implements WebMvcConfigurer {
private final CspReportMessageConverter cspReportMessageConverter;
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(cspReportMessageConverter); } }
|
控制层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import cn.hutool.core.bean.BeanUtil; import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController @RequestMapping("/csp-violation-report-endpoint") public class CspReportController {
@PostMapping(consumes = "application/csp-report") public ResponseEntity<Void> receiveCspReport(@RequestBody CspViolationReportWrapper cspViolationReportWrapper) {
CspViolationReportWrapper.CspViolationReport cspReport = cspViolationReportWrapper.getCspReport(); CspViolationReport cspViolationReport = BeanUtil.copyProperties(cspReport, CspViolationReport.class);
cspViolationReport.setTimestamp(System.currentTimeMillis()); System.out.println("CSP Violation Report: " + cspViolationReport);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); } }
|