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