    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}