|
8 | 8 | package org.roda.wui.filter; |
9 | 9 |
|
10 | 10 | import java.io.IOException; |
| 11 | +import java.util.HashMap; |
| 12 | +import java.util.List; |
| 13 | +import java.util.Map; |
| 14 | + |
| 15 | +import org.apache.commons.configuration.Configuration; |
| 16 | +import org.roda.core.RodaCoreFactory; |
| 17 | +import org.roda.core.common.RodaUtils; |
| 18 | +import org.slf4j.Logger; |
| 19 | +import org.slf4j.LoggerFactory; |
11 | 20 |
|
12 | 21 | import jakarta.servlet.Filter; |
13 | 22 | import jakarta.servlet.FilterChain; |
|
18 | 27 | import jakarta.servlet.http.HttpServletResponse; |
19 | 28 |
|
20 | 29 | public class SecurityHeadersFilter implements Filter { |
| 30 | + private static final Logger LOGGER = LoggerFactory.getLogger(SecurityHeadersFilter.class); |
| 31 | + private final Map<String, String> headers = new HashMap<>(); |
| 32 | + private final static String SECURITY_HEADER_PROPERTY_PREFIX = "ui.filter.security-headers[]"; |
| 33 | + private Boolean isInit = false; |
21 | 34 |
|
22 | 35 | @Override |
23 | | - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
24 | | - throws IOException, ServletException { |
25 | | - HttpServletResponse httpServletResponse = (HttpServletResponse) response; |
| 36 | + public void init(FilterConfig filterConfig) { |
26 | 37 |
|
27 | | - httpServletResponse.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains"); |
28 | | - httpServletResponse.setHeader("Content-Security-Policy", |
29 | | - "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com " |
30 | | - + "https://www.google-analytics.com https://www.gstatic.com http://127.0.0.1:9876 http://localhost:9876; " |
31 | | - + "style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';"); |
32 | | - httpServletResponse.setHeader("X-XSS-Protection", "1; mode=block"); |
33 | | - httpServletResponse.setHeader("X-Permitted-Cross-Domain-Policies", "none"); |
34 | | - httpServletResponse.setHeader("Feature-Policy", |
35 | | - "camera 'none'; fullscreen 'self'; geolocation *; " + "microphone 'self'"); |
36 | | - httpServletResponse.setHeader("X-Frame-Options", "SAMEORIGIN"); |
37 | | - httpServletResponse.setHeader("X-Content-Type-Options", "nosniff"); |
38 | | - httpServletResponse.setHeader("Referrer-Policy", "no-referrer"); |
39 | | - httpServletResponse.setHeader("Permissions-Policy", "geolocation=(self)"); |
| 38 | + } |
40 | 39 |
|
41 | | - chain.doFilter(request, response); |
| 40 | + private void initSecurityHeaders() { |
| 41 | + if (isInit) { |
| 42 | + return; |
| 43 | + } |
| 44 | + |
| 45 | + final Configuration rodaConfig = RodaCoreFactory.getRodaConfiguration(); |
| 46 | + if (rodaConfig == null) { |
| 47 | + LOGGER.info("RODA configuration not available yet. Delaying init of SecurityHeadersFilter."); |
| 48 | + } else { |
| 49 | + List<String> headersNames = RodaUtils.copyList(rodaConfig.getList(SECURITY_HEADER_PROPERTY_PREFIX)); |
| 50 | + |
| 51 | + for (String headersName : headersNames) { |
| 52 | + String value = rodaConfig.getString(SECURITY_HEADER_PROPERTY_PREFIX + "." + headersName, null); |
| 53 | + if (value != null) { |
| 54 | + headers.put(headersName, value); |
| 55 | + } |
| 56 | + } |
| 57 | + isInit = true; |
| 58 | + LOGGER.info("SecurityHeadersFilter initialized with {} headers", headers.size()); |
| 59 | + } |
42 | 60 | } |
43 | 61 |
|
44 | 62 | @Override |
45 | | - public void init(FilterConfig filterConfig) { |
| 63 | + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
| 64 | + throws IOException, ServletException { |
| 65 | + initSecurityHeaders(); |
| 66 | + HttpServletResponse httpServletResponse = (HttpServletResponse) response; |
| 67 | + headers.forEach(httpServletResponse::setHeader); |
| 68 | + chain.doFilter(request, response); |
46 | 69 | } |
47 | 70 |
|
48 | 71 | @Override |
|
0 commit comments