001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.util; 018 019import javax.servlet.http.Cookie; 020import javax.servlet.http.HttpServletResponse; 021 022import org.apache.commons.logging.Log; 023import org.apache.commons.logging.LogFactory; 024 025import org.springframework.lang.Nullable; 026import org.springframework.util.Assert; 027 028/** 029 * Helper class for cookie generation, carrying cookie descriptor settings 030 * as bean properties and being able to add and remove cookie to/from a 031 * given response. 032 * 033 * <p>Can serve as base class for components that generate specific cookies, 034 * such as CookieLocaleResolver and CookieThemeResolver. 035 * 036 * @author Juergen Hoeller 037 * @since 1.1.4 038 * @see #addCookie 039 * @see #removeCookie 040 * @see org.springframework.web.servlet.i18n.CookieLocaleResolver 041 * @see org.springframework.web.servlet.theme.CookieThemeResolver 042 */ 043public class CookieGenerator { 044 045 /** 046 * Default path that cookies will be visible to: "/", i.e. the entire server. 047 */ 048 public static final String DEFAULT_COOKIE_PATH = "/"; 049 050 051 protected final Log logger = LogFactory.getLog(getClass()); 052 053 @Nullable 054 private String cookieName; 055 056 @Nullable 057 private String cookieDomain; 058 059 private String cookiePath = DEFAULT_COOKIE_PATH; 060 061 @Nullable 062 private Integer cookieMaxAge; 063 064 private boolean cookieSecure = false; 065 066 private boolean cookieHttpOnly = false; 067 068 069 /** 070 * Use the given name for cookies created by this generator. 071 * @see javax.servlet.http.Cookie#getName() 072 */ 073 public void setCookieName(@Nullable String cookieName) { 074 this.cookieName = cookieName; 075 } 076 077 /** 078 * Return the given name for cookies created by this generator. 079 */ 080 @Nullable 081 public String getCookieName() { 082 return this.cookieName; 083 } 084 085 /** 086 * Use the given domain for cookies created by this generator. 087 * The cookie is only visible to servers in this domain. 088 * @see javax.servlet.http.Cookie#setDomain 089 */ 090 public void setCookieDomain(@Nullable String cookieDomain) { 091 this.cookieDomain = cookieDomain; 092 } 093 094 /** 095 * Return the domain for cookies created by this generator, if any. 096 */ 097 @Nullable 098 public String getCookieDomain() { 099 return this.cookieDomain; 100 } 101 102 /** 103 * Use the given path for cookies created by this generator. 104 * The cookie is only visible to URLs in this path and below. 105 * @see javax.servlet.http.Cookie#setPath 106 */ 107 public void setCookiePath(String cookiePath) { 108 this.cookiePath = cookiePath; 109 } 110 111 /** 112 * Return the path for cookies created by this generator. 113 */ 114 public String getCookiePath() { 115 return this.cookiePath; 116 } 117 118 /** 119 * Use the given maximum age (in seconds) for cookies created by this generator. 120 * Useful special value: -1 ... not persistent, deleted when client shuts down. 121 * <p>Default is no specific maximum age at all, using the Servlet container's 122 * default. 123 * @see javax.servlet.http.Cookie#setMaxAge 124 */ 125 public void setCookieMaxAge(@Nullable Integer cookieMaxAge) { 126 this.cookieMaxAge = cookieMaxAge; 127 } 128 129 /** 130 * Return the maximum age for cookies created by this generator. 131 */ 132 @Nullable 133 public Integer getCookieMaxAge() { 134 return this.cookieMaxAge; 135 } 136 137 /** 138 * Set whether the cookie should only be sent using a secure protocol, 139 * such as HTTPS (SSL). This is an indication to the receiving browser, 140 * not processed by the HTTP server itself. 141 * <p>Default is "false". 142 * @see javax.servlet.http.Cookie#setSecure 143 */ 144 public void setCookieSecure(boolean cookieSecure) { 145 this.cookieSecure = cookieSecure; 146 } 147 148 /** 149 * Return whether the cookie should only be sent using a secure protocol, 150 * such as HTTPS (SSL). 151 */ 152 public boolean isCookieSecure() { 153 return this.cookieSecure; 154 } 155 156 /** 157 * Set whether the cookie is supposed to be marked with the "HttpOnly" attribute. 158 * <p>Default is "false". 159 * @see javax.servlet.http.Cookie#setHttpOnly 160 */ 161 public void setCookieHttpOnly(boolean cookieHttpOnly) { 162 this.cookieHttpOnly = cookieHttpOnly; 163 } 164 165 /** 166 * Return whether the cookie is supposed to be marked with the "HttpOnly" attribute. 167 */ 168 public boolean isCookieHttpOnly() { 169 return this.cookieHttpOnly; 170 } 171 172 173 /** 174 * Add a cookie with the given value to the response, 175 * using the cookie descriptor settings of this generator. 176 * <p>Delegates to {@link #createCookie} for cookie creation. 177 * @param response the HTTP response to add the cookie to 178 * @param cookieValue the value of the cookie to add 179 * @see #setCookieName 180 * @see #setCookieDomain 181 * @see #setCookiePath 182 * @see #setCookieMaxAge 183 */ 184 public void addCookie(HttpServletResponse response, String cookieValue) { 185 Assert.notNull(response, "HttpServletResponse must not be null"); 186 Cookie cookie = createCookie(cookieValue); 187 Integer maxAge = getCookieMaxAge(); 188 if (maxAge != null) { 189 cookie.setMaxAge(maxAge); 190 } 191 if (isCookieSecure()) { 192 cookie.setSecure(true); 193 } 194 if (isCookieHttpOnly()) { 195 cookie.setHttpOnly(true); 196 } 197 response.addCookie(cookie); 198 if (logger.isTraceEnabled()) { 199 logger.trace("Added cookie [" + getCookieName() + "=" + cookieValue + "]"); 200 } 201 } 202 203 /** 204 * Remove the cookie that this generator describes from the response. 205 * Will generate a cookie with empty value and max age 0. 206 * <p>Delegates to {@link #createCookie} for cookie creation. 207 * @param response the HTTP response to remove the cookie from 208 * @see #setCookieName 209 * @see #setCookieDomain 210 * @see #setCookiePath 211 */ 212 public void removeCookie(HttpServletResponse response) { 213 Assert.notNull(response, "HttpServletResponse must not be null"); 214 Cookie cookie = createCookie(""); 215 cookie.setMaxAge(0); 216 if (isCookieSecure()) { 217 cookie.setSecure(true); 218 } 219 if (isCookieHttpOnly()) { 220 cookie.setHttpOnly(true); 221 } 222 response.addCookie(cookie); 223 if (logger.isTraceEnabled()) { 224 logger.trace("Removed cookie '" + getCookieName() + "'"); 225 } 226 } 227 228 /** 229 * Create a cookie with the given value, using the cookie descriptor 230 * settings of this generator (except for "cookieMaxAge"). 231 * @param cookieValue the value of the cookie to crate 232 * @return the cookie 233 * @see #setCookieName 234 * @see #setCookieDomain 235 * @see #setCookiePath 236 */ 237 protected Cookie createCookie(String cookieValue) { 238 Cookie cookie = new Cookie(getCookieName(), cookieValue); 239 if (getCookieDomain() != null) { 240 cookie.setDomain(getCookieDomain()); 241 } 242 cookie.setPath(getCookiePath()); 243 return cookie; 244 } 245 246}