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