001    // Copyright 2008, 2009, 2010, 2011 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    
015    package org.apache.tapestry5.internal.services;
016    
017    import org.apache.tapestry5.Link;
018    import org.apache.tapestry5.MetaDataConstants;
019    import org.apache.tapestry5.SymbolConstants;
020    import org.apache.tapestry5.ioc.annotations.Symbol;
021    import org.apache.tapestry5.services.*;
022    
023    import java.io.IOException;
024    
025    public class RequestSecurityManagerImpl implements RequestSecurityManager
026    {
027        private final Request request;
028    
029        private final Response response;
030    
031        private final MetaDataLocator locator;
032    
033        private final boolean securityEnabled;
034    
035        private final ComponentEventLinkEncoder componentEventLinkEncoder;
036    
037        public RequestSecurityManagerImpl(Request request, Response response,
038                                          ComponentEventLinkEncoder componentEventLinkEncoder, MetaDataLocator locator, @Symbol(SymbolConstants.SECURE_ENABLED)
039        boolean securityEnabled)
040        {
041            this.request = request;
042            this.response = response;
043            this.componentEventLinkEncoder = componentEventLinkEncoder;
044            this.locator = locator;
045            this.securityEnabled = securityEnabled;
046        }
047    
048        public boolean checkForInsecureComponentEventRequest(ComponentEventRequestParameters parameters) throws IOException
049        {
050            if (!needsRedirect(parameters.getActivePageName()))
051            {
052                return false;
053            }
054    
055            // Page is secure but request is not, so redirect.
056            // We can safely ignore the forForm parameter since secure form requests are always done from
057            // an already secured page
058    
059            Link link = componentEventLinkEncoder.createComponentEventLink(parameters, false);
060    
061            response.sendRedirect(link);
062    
063            return true;
064        }
065    
066        public boolean checkForInsecurePageRenderRequest(PageRenderRequestParameters parameters) throws IOException
067        {
068            if (!needsRedirect(parameters.getLogicalPageName()))
069                return false;
070    
071            // Page is secure but request is not, so redirect.
072    
073            Link link = componentEventLinkEncoder.createPageRenderLink(parameters);
074    
075            response.sendRedirect(link);
076    
077            return true;
078        }
079    
080        private boolean needsRedirect(String pageName)
081        {
082            if (!securityEnabled)
083            {
084                return false;
085            }
086    
087            // We don't (at this time) redirect from secure to insecure, just from insecure to secure.
088    
089            if (request.isSecure())
090            {
091                return false;
092            }
093    
094            if (!isSecure(pageName))
095            {
096                return false;
097            }
098    
099            return true;
100        }
101    
102        private boolean isSecure(String pageName)
103        {
104            return locator.findMeta(MetaDataConstants.SECURE_PAGE, pageName, Boolean.class);
105        }
106    
107        public LinkSecurity checkPageSecurity(String pageName)
108        {
109            if (!securityEnabled)
110            {
111                return request.isSecure() ? LinkSecurity.SECURE : LinkSecurity.INSECURE;
112            }
113    
114            boolean securePage = isSecure(pageName);
115    
116            if (request.isSecure() == securePage)
117            {
118                return securePage ? LinkSecurity.SECURE : LinkSecurity.INSECURE;
119            }
120    
121            // Return a value that will, ultimately, force an absolute URL.
122    
123            return securePage ? LinkSecurity.FORCE_SECURE : LinkSecurity.FORCE_INSECURE;
124        }
125    }