001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.shiro.web.util;
020
021import org.apache.shiro.lang.util.StringUtils;
022
023import javax.servlet.http.HttpServletRequest;
024
025/**
026 * Utility class for CORS request handling based on the W3.
027 *
028 * @see <a href="https://fetch.spec.whatwg.org/#http-cors-protocol">CORS W3C recommendation</a>
029 * @since 2.0.7
030 */
031public interface CorsUtils {
032
033    /**
034     * The HTTP {@code Origin} header field name.
035     * @see <a href="https://tools.ietf.org/html/rfc6454">RFC 6454</a>
036     */
037    String ORIGIN = "Origin";
038    /**
039     * The CORS {@code Access-Control-Request-Method} request header field name.
040     * @see <a href="https://www.w3.org/TR/cors/">CORS W3C recommendation</a>
041     */
042    String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
043
044    String OPTIONS = "OPTIONS";
045
046    /**
047     * Determines whether the given {@link HttpServletRequest} represents a CORS preflight request.
048     * <p>
049     * A CORS preflight request is an {@code OPTIONS} request sent by browsers before the actual
050     * cross-origin request, to verify that the target server allows the actual request's
051     * method and headers.
052     * </p>
053     *
054     * <p>This method returns {@code true} if and only if:</p>
055     * <ul>
056     *   <li>The HTTP method is {@code OPTIONS},</li>
057     *   <li>The {@code Origin} header is present, and</li>
058     *   <li>The {@code Access-Control-Request-Method} header is present.</li>
059     * </ul>
060     *
061     * @param request the incoming HTTP request to inspect (must not be {@code null})
062     * @return {@code true} if the request is a valid CORS preflight request; {@code false} otherwise
063     */
064    static boolean isPreFlightRequest(HttpServletRequest request) {
065        return (request.getMethod().equals(OPTIONS)
066                && StringUtils.hasText(request.getHeader(ORIGIN))
067                && StringUtils.hasText(request.getHeader(ACCESS_CONTROL_REQUEST_METHOD)));
068    }
069}