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
015package org.apache.tapestry5.internal.services;
016
017import org.apache.tapestry5.Link;
018import org.apache.tapestry5.MetaDataConstants;
019import org.apache.tapestry5.SymbolConstants;
020import org.apache.tapestry5.ioc.annotations.Symbol;
021import org.apache.tapestry5.services.*;
022
023import java.io.IOException;
024
025public 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}