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.filter; 018 019import java.io.IOException; 020 021import javax.servlet.FilterChain; 022import javax.servlet.ServletException; 023import javax.servlet.http.HttpServletRequest; 024import javax.servlet.http.HttpServletResponse; 025 026import org.springframework.lang.Nullable; 027import org.springframework.util.Assert; 028 029/** 030 * Servlet Filter that allows one to specify a character encoding for requests. 031 * This is useful because current browsers typically do not set a character 032 * encoding even if specified in the HTML page or form. 033 * 034 * <p>This filter can either apply its encoding if the request does not already 035 * specify an encoding, or enforce this filter's encoding in any case 036 * ("forceEncoding"="true"). In the latter case, the encoding will also be 037 * applied as default response encoding (although this will usually be overridden 038 * by a full content type set in the view). 039 * 040 * @author Juergen Hoeller 041 * @since 15.03.2004 042 * @see #setEncoding 043 * @see #setForceEncoding 044 * @see javax.servlet.http.HttpServletRequest#setCharacterEncoding 045 * @see javax.servlet.http.HttpServletResponse#setCharacterEncoding 046 */ 047public class CharacterEncodingFilter extends OncePerRequestFilter { 048 049 @Nullable 050 private String encoding; 051 052 private boolean forceRequestEncoding = false; 053 054 private boolean forceResponseEncoding = false; 055 056 057 /** 058 * Create a default {@code CharacterEncodingFilter}, 059 * with the encoding to be set via {@link #setEncoding}. 060 * @see #setEncoding 061 */ 062 public CharacterEncodingFilter() { 063 } 064 065 /** 066 * Create a {@code CharacterEncodingFilter} for the given encoding. 067 * @param encoding the encoding to apply 068 * @since 4.2.3 069 * @see #setEncoding 070 */ 071 public CharacterEncodingFilter(String encoding) { 072 this(encoding, false); 073 } 074 075 /** 076 * Create a {@code CharacterEncodingFilter} for the given encoding. 077 * @param encoding the encoding to apply 078 * @param forceEncoding whether the specified encoding is supposed to 079 * override existing request and response encodings 080 * @since 4.2.3 081 * @see #setEncoding 082 * @see #setForceEncoding 083 */ 084 public CharacterEncodingFilter(String encoding, boolean forceEncoding) { 085 this(encoding, forceEncoding, forceEncoding); 086 } 087 088 /** 089 * Create a {@code CharacterEncodingFilter} for the given encoding. 090 * @param encoding the encoding to apply 091 * @param forceRequestEncoding whether the specified encoding is supposed to 092 * override existing request encodings 093 * @param forceResponseEncoding whether the specified encoding is supposed to 094 * override existing response encodings 095 * @since 4.3 096 * @see #setEncoding 097 * @see #setForceRequestEncoding(boolean) 098 * @see #setForceResponseEncoding(boolean) 099 */ 100 public CharacterEncodingFilter(String encoding, boolean forceRequestEncoding, boolean forceResponseEncoding) { 101 Assert.hasLength(encoding, "Encoding must not be empty"); 102 this.encoding = encoding; 103 this.forceRequestEncoding = forceRequestEncoding; 104 this.forceResponseEncoding = forceResponseEncoding; 105 } 106 107 108 /** 109 * Set the encoding to use for requests. This encoding will be passed into a 110 * {@link javax.servlet.http.HttpServletRequest#setCharacterEncoding} call. 111 * <p>Whether this encoding will override existing request encodings 112 * (and whether it will be applied as default response encoding as well) 113 * depends on the {@link #setForceEncoding "forceEncoding"} flag. 114 */ 115 public void setEncoding(@Nullable String encoding) { 116 this.encoding = encoding; 117 } 118 119 /** 120 * Return the configured encoding for requests and/or responses. 121 * @since 4.3 122 */ 123 @Nullable 124 public String getEncoding() { 125 return this.encoding; 126 } 127 128 /** 129 * Set whether the configured {@link #setEncoding encoding} of this filter 130 * is supposed to override existing request and response encodings. 131 * <p>Default is "false", i.e. do not modify the encoding if 132 * {@link javax.servlet.http.HttpServletRequest#getCharacterEncoding()} 133 * returns a non-null value. Switch this to "true" to enforce the specified 134 * encoding in any case, applying it as default response encoding as well. 135 * <p>This is the equivalent to setting both {@link #setForceRequestEncoding(boolean)} 136 * and {@link #setForceResponseEncoding(boolean)}. 137 * @see #setForceRequestEncoding(boolean) 138 * @see #setForceResponseEncoding(boolean) 139 */ 140 public void setForceEncoding(boolean forceEncoding) { 141 this.forceRequestEncoding = forceEncoding; 142 this.forceResponseEncoding = forceEncoding; 143 } 144 145 /** 146 * Set whether the configured {@link #setEncoding encoding} of this filter 147 * is supposed to override existing request encodings. 148 * <p>Default is "false", i.e. do not modify the encoding if 149 * {@link javax.servlet.http.HttpServletRequest#getCharacterEncoding()} 150 * returns a non-null value. Switch this to "true" to enforce the specified 151 * encoding in any case. 152 * @since 4.3 153 */ 154 public void setForceRequestEncoding(boolean forceRequestEncoding) { 155 this.forceRequestEncoding = forceRequestEncoding; 156 } 157 158 /** 159 * Return whether the encoding should be forced on requests. 160 * @since 4.3 161 */ 162 public boolean isForceRequestEncoding() { 163 return this.forceRequestEncoding; 164 } 165 166 /** 167 * Set whether the configured {@link #setEncoding encoding} of this filter 168 * is supposed to override existing response encodings. 169 * <p>Default is "false", i.e. do not modify the encoding. 170 * Switch this to "true" to enforce the specified encoding 171 * for responses in any case. 172 * @since 4.3 173 */ 174 public void setForceResponseEncoding(boolean forceResponseEncoding) { 175 this.forceResponseEncoding = forceResponseEncoding; 176 } 177 178 /** 179 * Return whether the encoding should be forced on responses. 180 * @since 4.3 181 */ 182 public boolean isForceResponseEncoding() { 183 return this.forceResponseEncoding; 184 } 185 186 187 @Override 188 protected void doFilterInternal( 189 HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 190 throws ServletException, IOException { 191 192 String encoding = getEncoding(); 193 if (encoding != null) { 194 if (isForceRequestEncoding() || request.getCharacterEncoding() == null) { 195 request.setCharacterEncoding(encoding); 196 } 197 if (isForceResponseEncoding()) { 198 response.setCharacterEncoding(encoding); 199 } 200 } 201 filterChain.doFilter(request, response); 202 } 203 204}