001
014
015 package com.liferay.portlet;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.portlet.ActionResult;
021 import com.liferay.portal.kernel.portlet.PortletContainer;
022 import com.liferay.portal.kernel.portlet.PortletContainerException;
023 import com.liferay.portal.kernel.portlet.PortletContainerUtil;
024 import com.liferay.portal.kernel.resiliency.spi.SPIUtil;
025 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
026 import com.liferay.portal.kernel.servlet.HttpHeaders;
027 import com.liferay.portal.kernel.servlet.TempAttributesServletRequest;
028 import com.liferay.portal.kernel.struts.LastPath;
029 import com.liferay.portal.kernel.util.CharPool;
030 import com.liferay.portal.kernel.util.GetterUtil;
031 import com.liferay.portal.kernel.util.WebKeys;
032 import com.liferay.portal.model.Layout;
033 import com.liferay.portal.model.LayoutType;
034 import com.liferay.portal.model.LayoutTypeAccessPolicy;
035 import com.liferay.portal.model.LayoutTypePortlet;
036 import com.liferay.portal.model.Portlet;
037 import com.liferay.portal.security.auth.AuthTokenUtil;
038 import com.liferay.portal.security.auth.AuthTokenWhitelistUtil;
039 import com.liferay.portal.security.auth.PrincipalException;
040 import com.liferay.portal.theme.ThemeDisplay;
041 import com.liferay.portal.util.PortalUtil;
042 import com.liferay.portal.util.PropsValues;
043
044 import java.util.List;
045 import java.util.Map;
046
047 import javax.portlet.Event;
048
049 import javax.servlet.RequestDispatcher;
050 import javax.servlet.http.HttpServletRequest;
051 import javax.servlet.http.HttpServletResponse;
052
053
057 @DoPrivileged
058 public class SecurityPortletContainerWrapper implements PortletContainer {
059
060 public static PortletContainer createSecurityPortletContainerWrapper(
061 PortletContainer portletContainer) {
062
063 if (!SPIUtil.isSPI()) {
064 portletContainer = new SecurityPortletContainerWrapper(
065 portletContainer);
066 }
067
068 return portletContainer;
069 }
070
071 public SecurityPortletContainerWrapper(PortletContainer portletContainer) {
072 _portletContainer = portletContainer;
073 }
074
075 @Override
076 public void preparePortlet(HttpServletRequest request, Portlet portlet)
077 throws PortletContainerException {
078
079 _portletContainer.preparePortlet(request, portlet);
080 }
081
082 @Override
083 public ActionResult processAction(
084 HttpServletRequest request, HttpServletResponse response,
085 Portlet portlet)
086 throws PortletContainerException {
087
088 try {
089 HttpServletRequest ownerLayoutRequest =
090 getOwnerLayoutRequestWrapper(request, portlet);
091
092 checkAction(ownerLayoutRequest, portlet);
093
094 return _portletContainer.processAction(request, response, portlet);
095 }
096 catch (PrincipalException pe) {
097 return processActionException(request, response, portlet, pe);
098 }
099 catch (PortletContainerException pce) {
100 throw pce;
101 }
102 catch (Exception e) {
103 throw new PortletContainerException(e);
104 }
105 }
106
107 @Override
108 public List<Event> processEvent(
109 HttpServletRequest request, HttpServletResponse response,
110 Portlet portlet, Layout layout, Event event)
111 throws PortletContainerException {
112
113 return _portletContainer.processEvent(
114 request, response, portlet, layout, event);
115 }
116
117 @Override
118 public void render(
119 HttpServletRequest request, HttpServletResponse response,
120 Portlet portlet)
121 throws PortletContainerException {
122
123 try {
124 checkRender(request, portlet);
125
126 _portletContainer.render(request, response, portlet);
127 }
128 catch (PrincipalException pe) {
129 processRenderException(request, response, portlet);
130 }
131 catch (PortletContainerException pce) {
132 throw pce;
133 }
134 catch (Exception e) {
135 throw new PortletContainerException(e);
136 }
137 }
138
139 @Override
140 public void serveResource(
141 HttpServletRequest request, HttpServletResponse response,
142 Portlet portlet)
143 throws PortletContainerException {
144
145 try {
146 HttpServletRequest ownerLayoutRequest =
147 getOwnerLayoutRequestWrapper(request, portlet);
148
149 checkResource(ownerLayoutRequest, portlet);
150
151 _portletContainer.serveResource(request, response, portlet);
152 }
153 catch (PrincipalException pe) {
154 processServeResourceException(request, response, portlet, pe);
155 }
156 catch (PortletContainerException pce) {
157 throw pce;
158 }
159 catch (Exception e) {
160 throw new PortletContainerException(e);
161 }
162 }
163
164 protected void check(HttpServletRequest request, Portlet portlet)
165 throws Exception {
166
167 if (portlet == null) {
168 return;
169 }
170
171 if (!isValidPortletId(portlet.getPortletId())) {
172 if (_log.isWarnEnabled()) {
173 _log.warn("Invalid portlet ID " + portlet.getPortletId());
174 }
175
176 throw new PrincipalException(
177 "Invalid portlet ID " + portlet.getPortletId());
178 }
179
180 if (portlet.isUndeployedPortlet()) {
181 return;
182 }
183
184 Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
185
186 LayoutType layoutType = layout.getLayoutType();
187
188 LayoutTypeAccessPolicy layoutTypeAccessPolicy =
189 layoutType.getLayoutTypeAccessPolicy();
190
191 layoutTypeAccessPolicy.checkAccessAllowedToPortlet(
192 request, layout, portlet);
193 }
194
195 protected void checkAction(HttpServletRequest request, Portlet portlet)
196 throws Exception {
197
198 checkCSRFProtection(request, portlet);
199
200 check(request, portlet);
201 }
202
203 protected void checkCSRFProtection(
204 HttpServletRequest request, Portlet portlet)
205 throws PortalException {
206
207 Map<String, String> initParams = portlet.getInitParams();
208
209 boolean checkAuthToken = GetterUtil.getBoolean(
210 initParams.get("check-auth-token"), true);
211
212 if (AuthTokenWhitelistUtil.isPortletCSRFWhitelisted(request, portlet)) {
213 checkAuthToken = false;
214 }
215
216 if (checkAuthToken) {
217 AuthTokenUtil.checkCSRFToken(
218 request, SecurityPortletContainerWrapper.class.getName());
219 }
220 }
221
222 protected void checkRender(HttpServletRequest request, Portlet portlet)
223 throws Exception {
224
225 check(request, portlet);
226 }
227
228 protected void checkResource(HttpServletRequest request, Portlet portlet)
229 throws Exception {
230
231 check(request, portlet);
232 }
233
234 protected String getOriginalURL(HttpServletRequest request) {
235 LastPath lastPath = (LastPath)request.getAttribute(WebKeys.LAST_PATH);
236
237 if (lastPath == null) {
238 return String.valueOf(request.getRequestURI());
239 }
240
241 String portalURL = PortalUtil.getPortalURL(request);
242
243 return portalURL.concat(
244 lastPath.getContextPath()).concat(lastPath.getPath());
245 }
246
247 protected HttpServletRequest getOwnerLayoutRequestWrapper(
248 HttpServletRequest request, Portlet portlet)
249 throws Exception {
250
251 if (!PropsValues.PORTLET_EVENT_DISTRIBUTION_LAYOUT_SET ||
252 PropsValues.PORTLET_CROSS_LAYOUT_INVOCATION_MODE.equals("render")) {
253
254 return request;
255 }
256
257 Layout ownerLayout = null;
258 LayoutTypePortlet ownerLayoutTypePortlet = null;
259
260 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
261 WebKeys.THEME_DISPLAY);
262
263 Layout requestLayout = (Layout)request.getAttribute(WebKeys.LAYOUT);
264
265 List<LayoutTypePortlet> layoutTypePortlets =
266 PortletContainerUtil.getLayoutTypePortlets(requestLayout);
267
268 for (LayoutTypePortlet layoutTypePortlet : layoutTypePortlets) {
269 if (layoutTypePortlet.hasPortletId(portlet.getPortletId())) {
270 ownerLayoutTypePortlet = layoutTypePortlet;
271
272 ownerLayout = layoutTypePortlet.getLayout();
273
274 break;
275 }
276 }
277
278 if (ownerLayout == null) {
279 return request;
280 }
281
282 Layout currentLayout = themeDisplay.getLayout();
283
284 if (currentLayout.equals(ownerLayout)) {
285 return request;
286 }
287
288 ThemeDisplay themeDisplayClone = (ThemeDisplay)themeDisplay.clone();
289
290 themeDisplayClone.setLayout(ownerLayout);
291 themeDisplayClone.setLayoutTypePortlet(ownerLayoutTypePortlet);
292
293 TempAttributesServletRequest tempAttributesServletRequest =
294 new TempAttributesServletRequest(request);
295
296 tempAttributesServletRequest.setTempAttribute(
297 WebKeys.LAYOUT, ownerLayout);
298 tempAttributesServletRequest.setTempAttribute(
299 WebKeys.THEME_DISPLAY, themeDisplayClone);
300
301 return tempAttributesServletRequest;
302 }
303
304 protected boolean isValidPortletId(String portletId) {
305 for (int i = 0; i < portletId.length(); i++) {
306 char c = portletId.charAt(i);
307
308 if ((c >= CharPool.LOWER_CASE_A) && (c <= CharPool.LOWER_CASE_Z)) {
309 continue;
310 }
311
312 if ((c >= CharPool.UPPER_CASE_A) && (c <= CharPool.UPPER_CASE_Z)) {
313 continue;
314 }
315
316 if ((c >= CharPool.NUMBER_0) && (c <= CharPool.NUMBER_9)) {
317 continue;
318 }
319
320 if ((c == CharPool.POUND) || (c == CharPool.UNDERLINE)) {
321 continue;
322 }
323
324 return false;
325 }
326
327 return true;
328 }
329
330 protected ActionResult processActionException(
331 HttpServletRequest request, HttpServletResponse response,
332 Portlet portlet, PrincipalException pe) {
333
334 if (_log.isDebugEnabled()) {
335 _log.debug(pe);
336 }
337
338 String url = getOriginalURL(request);
339
340 if (_log.isWarnEnabled()) {
341 _log.warn(
342 String.format(
343 "User %s is not allowed to access URL %s and portlet %s",
344 PortalUtil.getUserId(request), url,
345 portlet.getPortletId()));
346 }
347
348 return ActionResult.EMPTY_ACTION_RESULT;
349 }
350
351 protected void processRenderException(
352 HttpServletRequest request, HttpServletResponse response,
353 Portlet portlet)
354 throws PortletContainerException {
355
356 String portletContent = null;
357
358 if (portlet.isShowPortletAccessDenied()) {
359 portletContent = "/html/portal/portlet_access_denied.jsp";
360 }
361
362 try {
363 if (portletContent != null) {
364 RequestDispatcher requestDispatcher =
365 request.getRequestDispatcher(portletContent);
366
367 requestDispatcher.include(request, response);
368 }
369 }
370 catch (Exception e) {
371 throw new PortletContainerException(e);
372 }
373 }
374
375 protected void processServeResourceException(
376 HttpServletRequest request, HttpServletResponse response,
377 Portlet portlet, PrincipalException pe) {
378
379 if (_log.isDebugEnabled()) {
380 _log.debug(pe);
381 }
382
383 String url = getOriginalURL(request);
384
385 response.setHeader(
386 HttpHeaders.CACHE_CONTROL,
387 HttpHeaders.CACHE_CONTROL_NO_CACHE_VALUE);
388
389 response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
390
391 if (_log.isWarnEnabled()) {
392 _log.warn(
393 "Reject serveResource for " + url + " on " +
394 portlet.getPortletId());
395 }
396 }
397
398 private static final Log _log = LogFactoryUtil.getLog(
399 SecurityPortletContainerWrapper.class);
400
401 private final PortletContainer _portletContainer;
402
403 }