All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.innoq.spring.cookie.flash.CookieFlashMapManager Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
/**
 * Copyright 2018 innoQ Deutschland GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.innoq.spring.cookie.flash;

import com.innoq.spring.cookie.security.CookieValueSigner;
import org.springframework.util.Assert;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.support.AbstractFlashMapManager;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.security.MessageDigest.isEqual;
import static org.springframework.web.util.WebUtils.getCookie;

public final class CookieFlashMapManager extends AbstractFlashMapManager {

    private static final String DEFAULT_COOKIE_NAME = "flash";

    private final FlashMapListCodec codec;
    private final CookieValueSigner signer;
    private final String cookieName;

    public CookieFlashMapManager(FlashMapListCodec codec,
            CookieValueSigner signer) {
        this(codec, signer, DEFAULT_COOKIE_NAME);
    }

    public CookieFlashMapManager(FlashMapListCodec codec,
            CookieValueSigner signer, String cookieName) {
        Assert.notNull(codec, "FlashMapListCodec must not be null");
        Assert.notNull(signer, "CookieValueSigner must not be null");
        Assert.hasText(cookieName, "Cookie name must not be null or empty");
        this.codec = codec;
        this.signer = signer;
        this.cookieName = cookieName;
    }

    @Override
    protected List retrieveFlashMaps(HttpServletRequest request) {
        final Cookie cookie = getCookie(request, cookieName);
        if (cookie == null) {
            return null;
        }

        final String value = cookie.getValue();
        return decode(value);
    }

    @Override
    protected void updateFlashMaps(List flashMaps,
            HttpServletRequest request, HttpServletResponse response) {
        final Cookie cookie = new Cookie(cookieName, null);
        cookie.setHttpOnly(true);
        cookie.setPath("/");

        if (flashMaps.isEmpty()) {
            cookie.setMaxAge(0);
        } else {
            final String value = encode(flashMaps);
            cookie.setValue(value);
        }
        response.addCookie(cookie);
    }

    @Override
    protected Object getFlashMapsMutex(HttpServletRequest request) {
        return null;
    }

    private List decode(String value) {
        final String[] signatureAndPayload = reverse(value).split("--", 2);
        if (signatureAndPayload.length != 2) {
            // TODO logging
            return null;
        }

        final String signature = reverse(signatureAndPayload[0]);
        final String payload = reverse(signatureAndPayload[1]);

        if (!isVerified(payload, signature)) {
            // TODO logging
            return null;
        }

        return codec.decode(payload);
    }


    private String encode(List flashMaps) {
        final String payload = codec.encode(flashMaps);
        final String signature = signer.sign(payload);
        return payload + "--" + signature;
    }

    private boolean isVerified(String payload, String digest) {
        final String signature = signer.sign(payload);
        return isEqual(digest.getBytes(UTF_8), signature.getBytes(UTF_8));
    }

    private static String reverse(String s) {
        return new StringBuilder(s).reverse().toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy