001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.internal.services; 014 015import org.apache.tapestry5.MetaDataConstants; 016import org.apache.tapestry5.http.services.Request; 017import org.apache.tapestry5.internal.InternalConstants; 018import org.apache.tapestry5.services.ComponentEventRequestParameters; 019import org.apache.tapestry5.services.ComponentRequestFilter; 020import org.apache.tapestry5.services.ComponentRequestHandler; 021import org.apache.tapestry5.services.MetaDataLocator; 022import org.apache.tapestry5.services.PageRenderRequestParameters; 023import org.apache.tapestry5.services.security.ClientWhitelist; 024 025import java.io.IOException; 026 027/** 028 * Ensures that a component event request does not reach a page annotated with 029 * {@link org.apache.tapestry5.annotations.WhitelistAccessOnly} from a client that is not on the 030 * {@linkplain ClientWhitelist whitelist}. 031 * 032 * A component event request identifies two pages: the active page (from the URL path) and the 033 * containing page (from the {@link InternalConstants#CONTAINER_PAGE_NAME} request parameter), whose 034 * component actually handles the event. Code from both pages runs for the request, so both are 035 * checked here. 036 * 037 * {@link ComponentEventLinkEncoderImpl} performs the same check while decoding the request, and is 038 * the gate that normally rejects these requests. This filter repeats it independently, so that any 039 * other route to the component event pipeline is covered as well. 040 * 041 * Page render requests are passed through: they are checked while decoding, and the page render 042 * dispatcher does not honour the "component not found" attribute used here to force a 404. 043 * 044 * @see org.apache.tapestry5.annotations.WhitelistAccessOnly 045 * @see MetaDataConstants#WHITELIST_ONLY_PAGE 046 * @since 5.9.2 047 */ 048public class WhitelistOnlyPageFilter implements ComponentRequestFilter 049{ 050 private final Request request; 051 052 private final MetaDataLocator metaDataLocator; 053 054 private final ClientWhitelist clientWhitelist; 055 056 public WhitelistOnlyPageFilter(Request request, MetaDataLocator metaDataLocator, ClientWhitelist clientWhitelist) 057 { 058 this.request = request; 059 this.metaDataLocator = metaDataLocator; 060 this.clientWhitelist = clientWhitelist; 061 } 062 063 @Override 064 public void handleComponentEvent(ComponentEventRequestParameters parameters, ComponentRequestHandler handler) 065 throws IOException 066 { 067 if (isWhitelistOnlyAndNotValid(parameters.getActivePageName()) 068 || isWhitelistOnlyAndNotValid(parameters.getContainingPageName())) 069 { 070 // Same treatment as a request naming a component that does not exist: handling is 071 // aborted and the dispatcher turns the request into a 404, rather than reporting that 072 // the page exists but is protected. 073 074 request.setAttribute(InternalConstants.REFERENCED_COMPONENT_NOT_FOUND, true); 075 076 return; 077 } 078 079 handler.handleComponentEvent(parameters); 080 } 081 082 @Override 083 public void handlePageRender(PageRenderRequestParameters parameters, ComponentRequestHandler handler) 084 throws IOException 085 { 086 // Pass these through to the default handler. 087 handler.handlePageRender(parameters); 088 } 089 090 private boolean isWhitelistOnlyAndNotValid(String canonicalizedPageName) 091 { 092 return metaDataLocator.findMeta(MetaDataConstants.WHITELIST_ONLY_PAGE, canonicalizedPageName, boolean.class) 093 && !clientWhitelist.isClientRequestOnWhitelist(); 094 } 095}