View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.internal.util;
21  
22  import org.apache.myfaces.tobago.context.ClientProperties;
23  import org.apache.myfaces.tobago.context.UserAgent;
24  import org.apache.myfaces.tobago.internal.config.ContentSecurityPolicy;
25  import org.apache.myfaces.tobago.portlet.PortletUtils;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  import javax.faces.context.FacesContext;
30  import javax.portlet.MimeResponse;
31  import javax.servlet.http.HttpServletResponse;
32  
33  public final class ResponseUtils {
34  
35    private static final Logger LOG = LoggerFactory.getLogger(ResponseUtils.class);
36  
37    private ResponseUtils() {
38      // utils class
39    }
40  
41    public static void ensureNoCacheHeader(FacesContext facesContext) {
42      Object response = facesContext.getExternalContext().getResponse();
43      if (response instanceof HttpServletResponse) {
44        ensureNoCacheHeader((HttpServletResponse) response);
45      } else if (PortletUtils.isPortletApiAvailable() && response instanceof MimeResponse) {
46        ensureNoCacheHeader((MimeResponse) response);
47      }
48    }
49  
50    public static void ensureNoCacheHeader(HttpServletResponse response) {
51      response.setHeader("Cache-Control", "no-cache,no-store,max-age=0,must-revalidate");
52      response.setHeader("Pragma", "no-cache");
53      response.setDateHeader("Expires", 0);
54      response.setDateHeader("max-age", 0);
55    }
56  
57    public static void ensureNoCacheHeader(MimeResponse response) {
58      // TODO validate this
59      response.getCacheControl().setExpirationTime(0);
60    }
61  
62    public static void ensureContentTypeHeader(FacesContext facesContext, String contentType) {
63      final Object response = facesContext.getExternalContext().getResponse();
64      if (response instanceof HttpServletResponse) {
65        ensureContentTypeHeader((HttpServletResponse) response, contentType);
66      } else if (PortletUtils.isPortletApiAvailable() && response instanceof MimeResponse) {
67        ensureContentTypeHeader((MimeResponse) response, contentType);
68      }
69    }
70  
71    public static void ensureContentTypeHeader(HttpServletResponse response, String contentType) {
72      if (!response.containsHeader("Content-Type")) {
73        response.setContentType(contentType);
74      } else {
75        final String responseContentType = response.getContentType();
76        if (!StringUtils.equalsIgnoreCaseAndWhitespace(responseContentType, contentType)) {
77          response.setContentType(contentType);
78          if (LOG.isDebugEnabled()) {
79            LOG.debug("Response already contains Header Content-Type '" + responseContentType
80                + "'. Overwriting with '" + contentType + "'");
81          }
82        }
83      }
84    }
85  
86    public static void ensureContentTypeHeader(MimeResponse response, String contentType) {
87      final String responseContentType = response.getContentType();
88      if (!StringUtils.equalsIgnoreCaseAndWhitespace(responseContentType, contentType)) {
89        response.setContentType(contentType);
90        if (LOG.isDebugEnabled()) {
91          LOG.debug("Response already contains Header Content-Type '" + responseContentType
92              + "'. Overwriting with '" + contentType + "'");
93        }
94      }
95    }
96  
97    public static void ensureContentSecurityPolicyHeader(
98        FacesContext facesContext, ContentSecurityPolicy contentSecurityPolicy) {
99      final Object response = facesContext.getExternalContext().getResponse();
100     if (response instanceof HttpServletResponse) {
101       final HttpServletResponse servletResponse = (HttpServletResponse) response;
102       final UserAgent userAgent = ClientProperties.getInstance(facesContext).getUserAgent();
103       final String[] cspHeaders;
104       switch (contentSecurityPolicy.getMode()) {
105         case OFF:
106           cspHeaders = new String[0];
107           break;
108         case ON:
109           cspHeaders = userAgent.getCspHeaders();
110           break;
111         case REPORT_ONLY:
112           cspHeaders = userAgent.getCspReportOnlyHeaders();
113           break;
114         default:
115           throw new IllegalArgumentException("Undefined mode: " + contentSecurityPolicy.getMode());
116       }
117       final StringBuilder builder = new StringBuilder();
118       for (String directive : contentSecurityPolicy.getDirectiveList()) {
119         builder.append(directive);
120         builder.append(";");
121       }
122       String value = builder.toString();
123       for (String cspHeader : cspHeaders) {
124         servletResponse.setHeader(cspHeader, value);
125       }
126     } else if (PortletUtils.isPortletApiAvailable() && response instanceof MimeResponse) {
127      // TODO Portlet
128       if (contentSecurityPolicy.getMode() != ContentSecurityPolicy.Mode.OFF) {
129         LOG.warn("CSP not implemented for Portlet!");
130       }
131     }
132   }
133 }