22
22
23
23
import org .springframework .security .web .header .HeaderWriter ;
24
24
25
+ import lombok .RequiredArgsConstructor ;
26
+
25
27
import ru .mystamps .web .Url ;
26
28
27
29
/**
28
30
* Implementation of {@link HeaderWriter} that is adding CSP header depending on the current URL.
29
31
*/
32
+ @ RequiredArgsConstructor
30
33
class ContentSecurityPolicyHeaderWriter implements HeaderWriter {
31
34
32
35
private static final String COLLECTION_INFO_PAGE_PATTERN =
@@ -71,14 +74,22 @@ class ContentSecurityPolicyHeaderWriter implements HeaderWriter {
71
74
" 'sha256-biLFinpqYMtWHmXfkA1BPeCY0/fNt46SAZ+BBk5YUog='"
72
75
+ " 'sha256-zQDRfdePzsm4666fPPtpna61v74bryIt2Xu5qx2rn4A='" ;
73
76
74
- // - 'self' is required for our own JS files
75
77
// - 'unsafe-inline' is required by jquery.min.js (that is using code inside of
76
78
// event handlers. We can't use hashing algorithms because they aren't supported
77
79
// for handlers. In future, we should get rid of jQuery or use
78
80
// 'unsafe-hashed-attributes' from CSP3. Details:
79
81
// https://github.com/jquery/jquery/blob/d71f6a53927ad02d/jquery.js#L1441-L1447
80
82
// and https://w3c.github.io/webappsec-csp/#unsafe-hashed-attributes-usage)
81
- private static final String SCRIPT_SRC = "script-src 'self' 'unsafe-inline'" ;
83
+ private static final String SCRIPT_SRC = "script-src 'unsafe-inline'" ;
84
+
85
+ // - 'self' is required for our own JS files
86
+ private static final String SCRIPTS_SELF = " 'self'" ;
87
+
88
+ // - 'https://stamps.filezz.ru' is required for our own JS files
89
+ // - 'https://maxcdn.bootstrapcdn.com' is required for bootstrap.min.js
90
+ // - 'https://yandex.st' is required for jquery.min.js
91
+ private static final String SCRIPTS_CDN =
92
+ " https://stamps.filezz.ru https://maxcdn.bootstrapcdn.com https://yandex.st" ;
82
93
83
94
// - 'unsafe-eval' is required by loader.js from Google Charts
84
95
// - 'https://www.gstatic.com' is required by Google Charts
@@ -99,13 +110,15 @@ class ContentSecurityPolicyHeaderWriter implements HeaderWriter {
99
110
// number of separators between directives
100
111
+ 5 ;
101
112
113
+ private final boolean useSingleHost ;
114
+
102
115
@ Override
103
116
public void writeHeaders (HttpServletRequest request , HttpServletResponse response ) {
104
117
String uri = request .getRequestURI ();
105
118
response .setHeader ("Content-Security-Policy-Report-Only" , constructDirectives (uri ));
106
119
}
107
120
108
- private static String constructDirectives (String uri ) {
121
+ private String constructDirectives (String uri ) {
109
122
boolean onCollectionInfoPage = uri .startsWith (COLLECTION_INFO_PAGE_PATTERN );
110
123
111
124
StringBuilder sb = new StringBuilder (MIN_HEADER_LENGTH );
@@ -127,7 +140,8 @@ private static String constructDirectives(String uri) {
127
140
}
128
141
129
142
sb .append (SEPARATOR )
130
- .append (SCRIPT_SRC );
143
+ .append (SCRIPT_SRC )
144
+ .append (useSingleHost ? SCRIPTS_SELF : SCRIPTS_CDN );
131
145
132
146
if (onCollectionInfoPage ) {
133
147
sb .append (SCRIPT_COLLECTION_INFO );
0 commit comments