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

com.github.kaizen4j.shiro.csrf.CookieCsrfTokenRepository Maven / Gradle / Ivy

The newest version!
package com.github.kaizen4j.shiro.csrf;

import com.github.kaizen4j.algorithm.encrypt.Des;
import com.github.kaizen4j.shiro.exception.InvalidCsrfTokenException;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.util.WebUtils;

/**
 * @author liuguowen
 */
public class CookieCsrfTokenRepository implements CsrfTokenRepository {

    private static final Logger logger = LoggerFactory.getLogger(CookieCsrfTokenRepository.class);

    private static final String DEFAULT_SECRET_KEY = Hex
            .encodeHexString(CookieCsrfTokenRepository.class.getName().getBytes());

    private static final String DEFAULT_CSRF_PARAMETER_NAME = "_csrf";

    private static final String DEFAULT_CSRF_HEADER_NAME = "X-CSRF-TOKEN";

    private static final String DEFAULT_CSRF_COOKIE_NAME = "XSRF-TOKEN";

    /**
     * The number of seconds in one hour (= 60 * 60).
     */
    private static final int ONE_HOUR = 60 * 60;

    private String parameterName = DEFAULT_CSRF_PARAMETER_NAME;

    private String headerName = DEFAULT_CSRF_HEADER_NAME;

    private String cookieName = DEFAULT_CSRF_COOKIE_NAME;

    private boolean cookieHttpOnly = true;

    private String cookiePath;

    private String secretKey = DEFAULT_SECRET_KEY;

    private int expireSeconds = ONE_HOUR;

    @Override
    public CsrfToken generateToken(HttpServletRequest request) {
        return new DefaultCsrfToken(headerName, parameterName, createNewToken());
    }

    @Override
    public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
        Cookie cookie = new SimpleCookie(cookieName);
        cookie.setHttpOnly(cookieHttpOnly);
        cookie.setSecure(request.isSecure());
        cookie.setMaxAge(expireSeconds);

        String tokenValue = Objects.isNull(token) ? StringUtils.EMPTY : token.getToken();
        cookie.setValue(tokenValue);

        if (StringUtils.isNotBlank(cookiePath)) {
            cookie.setPath(cookiePath);
        } else {
            cookie.setPath(getRequestContext(request));
        }

        cookie.saveTo(request, response);
    }

    @Override
    public CsrfToken loadToken(HttpServletRequest request) {
        // get the actual token from the cookie
        javax.servlet.http.Cookie cookie = WebUtils.getCookie(request, cookieName);
        if (Objects.isNull(cookie)) {
            return null;
        }

        String tokenValue = cookie.getValue();
        if (StringUtils.isBlank(tokenValue)) {
            return null;
        }

        if (this.checkToken(tokenValue)) {
            return new DefaultCsrfToken(headerName, parameterName, tokenValue);
        } else {
            throw new InvalidCsrfTokenException("Invalid csrf token: " + tokenValue);
        }
    }

    public void setParameterName(String parameterName) {
        Assert.notNull(parameterName, "parameterName is not null");
        this.parameterName = parameterName;
    }

    public void setHeaderName(String headerName) {
        Assert.notNull(headerName, "headerName is not null");
        this.headerName = headerName;
    }

    public String getCookieName() {
        return cookieName;
    }

    public void setCookieName(String cookieName) {
        this.cookieName = cookieName;
    }

    public String getCookiePath() {
        return cookiePath;
    }

    public void setCookiePath(String cookiePath) {
        this.cookiePath = cookiePath;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public int getExpireSeconds() {
        return expireSeconds;
    }

    public void setExpireSeconds(int expireSeconds) {
        this.expireSeconds = expireSeconds;
    }

    public void setCookieHttpOnly(boolean cookieHttpOnly) {
        this.cookieHttpOnly = cookieHttpOnly;
    }

    public static CookieCsrfTokenRepository withHttpOnlyFalse() {
        CookieCsrfTokenRepository result = new CookieCsrfTokenRepository();
        result.setCookieHttpOnly(false);
        return result;
    }

    private String getRequestContext(HttpServletRequest request) {
        String contextPath = request.getContextPath();
        return contextPath.length() > 0 ? contextPath : "/";
    }

    private String createNewToken() {
        StringBuilder token = new StringBuilder();
        String randomText = RandomStringUtils.randomAlphanumeric(16);
        token.append(randomText);
        token.append("-");
        token.append(Des.encrypt(randomText, secretKey));
        return token.toString();
    }

    private boolean checkToken(String token) {
        try {
            String[] tokens = token.split("-", 2);
            return StringUtils.equals(tokens[0], Des.decrypt(tokens[1], secretKey));
        } catch (Exception e) {
            logger.error("Check csrf token [{}] error", token, e);
            return false;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy