Servlet响应包装器正在Servlet过滤器中使用。这个想法是响应被操纵,并将“nonce”值注入表单中,作为防御CSRF攻击的一部分。
网络应用程序无处不在使用UTF-8。当Servlet过滤器不存在时,没有问题。添加过滤器时,会出现编码问题。 (似乎响应回复到8859-1。)
代码的内容:
final class CsrfResponseWrapper extends AbstractResponseWrapper {
...
byte[] modifyResponse(byte[] aInputResponse){
...
String originalInput = new String(aInputResponse, encoding);
String modifiedResult = addHiddenParamToPostedForms(originalInput);
result = modifiedResult.getBytes(encoding);
...
}
...
}
据我了解,byte-land和String-land之间的转换应指定编码。正如你所看到的,这在两个地方就完成了。 'encoding'变量的值是'UTF-8'; String本身的更改是标准字符串操作(使用正则表达式),并且从不指定编码(addHiddenParamToPostedForms)。
我对编码的错误在哪里?
编辑: 这是基类(对不起,它很长):
package hirondelle.web4j.security;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
/**
Abstract Base Class for altering response content.
(May be useful in future contexts as well. For now, keep package-private.)
*/
abstract class AbstractResponseWrapper extends HttpServletResponseWrapper {
AbstractResponseWrapper(ServletResponse aServletResponse) throws IOException {
super((HttpServletResponse)aServletResponse);
fOutputStream = new ModifiedOutputStream(aServletResponse.getOutputStream());
fWriter = new PrintWriter(fOutputStream);
}
/** Return the modified response. */
abstract byte[] modifyResponse(byte[] aInputResponse);
/** Standard servlet method. */
public final ServletOutputStream getOutputStream() {
//fLogger.fine("Modified Response : Getting output stream.");
if ( fWriterReturned ) {
throw new IllegalStateException();
}
fOutputStreamReturned = true;
return fOutputStream;
}
/** Standard servlet method. */
public final PrintWriter getWriter() {
//fLogger.fine("Modified Response : Getting writer.");
if ( fOutputStreamReturned ) {
throw new IllegalStateException();
}
fWriterReturned = true;
return fWriter;
}
// PRIVATE
/*
Well-behaved servlets return either an OutputStream or a PrintWriter, but not both.
*/
private PrintWriter fWriter;
private ModifiedOutputStream fOutputStream;
/*
These items are used to implement conformance to the
javadoc for ServletResponse, regarding exceptions being thrown.
*/
private boolean fWriterReturned;
private boolean fOutputStreamReturned;
/** Modified low level output stream. */
private class ModifiedOutputStream extends ServletOutputStream {
public ModifiedOutputStream(ServletOutputStream aOutputStream) {
fServletOutputStream = aOutputStream;
fBuffer = new ByteArrayOutputStream();
}
/** Must be implemented to make this class concrete. */
public void write(int aByte) {
fBuffer.write(aByte);
}
public void close() throws IOException {
if ( !fIsClosed ){
processStream();
fServletOutputStream.close();
fIsClosed = true;
}
}
public void flush() throws IOException {
if ( fBuffer.size() != 0 ){
if ( !fIsClosed ) {
processStream();
fBuffer = new ByteArrayOutputStream();
}
}
}
/** Perform the core processing, by calling the abstract method. */
public void processStream() throws IOException {
fServletOutputStream.write(modifyResponse(fBuffer.toByteArray()));
fServletOutputStream.flush();
}
// PRIVATE //
private ServletOutputStream fServletOutputStream;
private ByteArrayOutputStream fBuffer;
/** Tracks if this stream has been closed. */
private boolean fIsClosed = false;
}
}
答案 0 :(得分:5)
来自new PrintWriter(OutputStream)
javadoc:
从现有的OutputStream创建一个没有自动行刷新的新PrintWriter。这个便利构造函数创建了必要的中间OutputStreamWriter,它将使用默认字符编码将字符转换为字节。
这是你的罪魁祸首。请查看OutputStreamWriter
,您可以在其中指定编码。
答案 1 :(得分:0)
您提供的代码似乎没有错误。
你在其他地方做什么?