提交 76ee4684 编写于 作者: B Brian Clozel

Selectively force encoding in CharacterEncodingFilter

Prior to this commit, setting the `forceEncoding` option would force
encoding on both requests and responses.

This commit adds two new setters and a new constructor to differentiate
both options: forcing the encoding on the request and/or on the
response.

You can now define this filter programmatically using those options or
update your servlet XML configuration like:

```
<filter>
  <filter-name>characterEncodingFilter</filter-name>
  <filter-class>o.sf.web.filter.CharacterEncodingFilter</filter-class>
  <init-param>
     <param-name>encoding</param-name>
     <param-value>UTF-8</param-value>
  </init-param>
  <init-param>
    <param-name>forceRequestEncoding</param-name>
    <param-value>true</param-value>
  </init-param>
  <init-param>
    <param-name>forceResponseEncoding</param-name>
    <param-value>false</param-value>
  </init-param>
</filter>

```

Issue: SPR-14240
上级 1be544f8
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -17,6 +17,7 @@
package org.springframework.web.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
......@@ -46,7 +47,9 @@ public class CharacterEncodingFilter extends OncePerRequestFilter {
private String encoding;
private boolean forceEncoding = false;
private boolean forceRequestEncoding = false;
private boolean forceResponseEncoding = false;
/**
......@@ -77,12 +80,28 @@ public class CharacterEncodingFilter extends OncePerRequestFilter {
* @see #setForceEncoding
*/
public CharacterEncodingFilter(String encoding, boolean forceEncoding) {
this(encoding, forceEncoding, forceEncoding);
}
/**
* Create a {@code CharacterEncodingFilter} for the given encoding.
* @param encoding the encoding to apply
* @param forceRequestEncoding whether the specified encoding is supposed to
* override existing request encodings
* @param forceResponseEncoding whether the specified encoding is supposed to
* override existing response encodings
* @since 4.3.0
* @see #setEncoding
* @see #setForceRequestEncoding(boolean)
* @see #setForceResponseEncoding(boolean)
*/
public CharacterEncodingFilter(String encoding, boolean forceRequestEncoding, boolean forceResponseEncoding) {
Assert.hasLength(encoding, "Encoding must not be empty");
this.encoding = encoding;
this.forceEncoding = forceEncoding;
this.forceRequestEncoding = forceRequestEncoding;
this.forceResponseEncoding = forceResponseEncoding;
}
/**
* Set the encoding to use for requests. This encoding will be passed into a
* {@link javax.servlet.http.HttpServletRequest#setCharacterEncoding} call.
......@@ -101,20 +120,50 @@ public class CharacterEncodingFilter extends OncePerRequestFilter {
* {@link javax.servlet.http.HttpServletRequest#getCharacterEncoding()}
* returns a non-null value. Switch this to "true" to enforce the specified
* encoding in any case, applying it as default response encoding as well.
* <p>This is the equivalent to setting both {@link #setForceRequestEncoding(boolean)}
* and {@link #setForceResponseEncoding(boolean)}.
* @see #setForceRequestEncoding(boolean)
* @see #setForceResponseEncoding(boolean)
*/
public void setForceEncoding(boolean forceEncoding) {
this.forceEncoding = forceEncoding;
this.forceRequestEncoding = forceEncoding;
this.forceResponseEncoding = forceEncoding;
}
/**
* Set whether the configured {@link #setEncoding encoding} of this filter
* is supposed to override existing request encodings.
* <p>Default is "false", i.e. do not modify the encoding if
* {@link javax.servlet.http.HttpServletRequest#getCharacterEncoding()}
* returns a non-null value. Switch this to "true" to enforce the specified
* encoding in any case.
* @since 4.3.0
*/
public void setForceRequestEncoding(boolean forceRequestEncoding) {
this.forceRequestEncoding = forceRequestEncoding;
}
/**
* Set whether the configured {@link #setEncoding encoding} of this filter
* is supposed to override existing response encodings.
* <p>Default is "false", i.e. do not modify the encoding.
* Switch this to "true" to enforce the specified encoding
* for responses in any case.
* @since 4.3.0
*/
public void setForceResponseEncoding(boolean forceResponseEncoding) {
this.forceResponseEncoding = forceResponseEncoding;
}
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if (this.forceEncoding) {
if (this.encoding != null) {
if (this.forceRequestEncoding || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(this.encoding);
}
if (this.forceResponseEncoding) {
response.setCharacterEncoding(this.encoding);
}
}
......
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -145,4 +145,26 @@ public class CharacterEncodingFilterTests {
verify(filterChain).doFilter(request, response);
}
// SPR-14240
@Test
public void setForceEncodingOnRequestOnly() throws Exception {
HttpServletRequest request = mock(HttpServletRequest.class);
request.setCharacterEncoding(ENCODING);
given(request.getAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE)).willReturn(null);
given(request.getAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX)).willReturn(null);
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain filterChain = mock(FilterChain.class);
CharacterEncodingFilter filter = new CharacterEncodingFilter(ENCODING, true, false);
filter.init(new MockFilterConfig(FILTER_NAME));
filter.doFilter(request, response, filterChain);
verify(request).setAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX, Boolean.TRUE);
verify(request).removeAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
verify(request, times(2)).setCharacterEncoding(ENCODING);
verify(response, never()).setCharacterEncoding(ENCODING);
verify(filterChain).doFilter(request, response);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册