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