001// Copyright 2008-2013, 2026 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.internal.services; 016 017import org.apache.tapestry5.MetaDataConstants; 018import org.apache.tapestry5.SymbolConstants; 019import org.apache.tapestry5.http.Link; 020import org.apache.tapestry5.http.LinkSecurity; 021import org.apache.tapestry5.http.services.Request; 022import org.apache.tapestry5.http.services.Response; 023import org.apache.tapestry5.ioc.annotations.Symbol; 024import org.apache.tapestry5.services.ComponentEventLinkEncoder; 025import org.apache.tapestry5.services.ComponentEventRequestParameters; 026import org.apache.tapestry5.services.MetaDataLocator; 027import org.apache.tapestry5.services.PageRenderRequestParameters; 028 029import java.io.IOException; 030 031public class RequestSecurityManagerImpl implements RequestSecurityManager 032{ 033 private final Request request; 034 035 private final Response response; 036 037 private final MetaDataLocator locator; 038 039 private final boolean securityEnabled; 040 041 private final ComponentEventLinkEncoder componentEventLinkEncoder; 042 043 public RequestSecurityManagerImpl(Request request, Response response, 044 ComponentEventLinkEncoder componentEventLinkEncoder, MetaDataLocator locator, @Symbol(SymbolConstants.SECURE_ENABLED) 045 boolean securityEnabled) 046 { 047 this.request = request; 048 this.response = response; 049 this.componentEventLinkEncoder = componentEventLinkEncoder; 050 this.locator = locator; 051 this.securityEnabled = securityEnabled; 052 } 053 054 public boolean checkForInsecureComponentEventRequest(ComponentEventRequestParameters parameters) throws IOException 055 { 056 // Both the active page and the containing page have code executing for this request, 057 // so @Secure on either must be honored. 058 if (!needsRedirect(parameters.getActivePageName()) 059 && !needsRedirect(parameters.getContainingPageName())) 060 { 061 return false; 062 } 063 064 // Page is secure but request is not, so redirect. 065 // We can safely ignore the forForm parameter since secure form requests are always done from 066 // an already secured page 067 068 Link link = componentEventLinkEncoder.createComponentEventLink(parameters, false); 069 070 response.sendRedirect(link); 071 072 return true; 073 } 074 075 public boolean checkForInsecurePageRenderRequest(PageRenderRequestParameters parameters) throws IOException 076 { 077 if (!needsRedirect(parameters.getLogicalPageName())) 078 return false; 079 080 // Page is secure but request is not, so redirect. 081 082 Link link = componentEventLinkEncoder.createPageRenderLink(parameters); 083 084 response.sendRedirect(link); 085 086 return true; 087 } 088 089 private boolean needsRedirect(String pageName) 090 { 091 if (!securityEnabled) 092 { 093 return false; 094 } 095 096 // We don't (at this time) redirect from secure to insecure, just from insecure to secure. 097 098 if (request.isSecure()) 099 { 100 return false; 101 } 102 103 if (!isSecure(pageName)) 104 { 105 return false; 106 } 107 108 return true; 109 } 110 111 private boolean isSecure(String pageName) 112 { 113 return locator.findMeta(MetaDataConstants.SECURE_PAGE, pageName, Boolean.class); 114 } 115 116 public LinkSecurity checkPageSecurity(String pageName) 117 { 118 if (!securityEnabled) 119 { 120 return request.isSecure() ? LinkSecurity.SECURE : LinkSecurity.INSECURE; 121 } 122 123 boolean securePage = isSecure(pageName); 124 125 if (request.isSecure() == securePage) 126 { 127 return securePage ? LinkSecurity.SECURE : LinkSecurity.INSECURE; 128 } 129 130 // Return a value that will, ultimately, force an absolute URL. 131 132 return securePage ? LinkSecurity.FORCE_SECURE : LinkSecurity.FORCE_INSECURE; 133 } 134}