Java Servlet响应包装器存在编码问题
servlet响应包装器正在servlet筛选器中使用。其思想是,响应被操纵,将“nonce”值注入表单中,作为抵御CSRF攻击的一部分 这个web应用程序到处都在使用UTF-8。当Servlet过滤器不存在时,没有问题。添加筛选器时,会出现编码问题。(似乎回复为8859-1。) 代码的核心:Java Servlet响应包装器存在编码问题,java,servlets,character-encoding,wrapper,servlet-filters,Java,Servlets,Character Encoding,Wrapper,Servlet Filters,servlet响应包装器正在servlet筛选器中使用。其思想是,响应被操纵,将“nonce”值注入表单中,作为抵御CSRF攻击的一部分 这个web应用程序到处都在使用UTF-8。当Servlet过滤器不存在时,没有问题。添加筛选器时,会出现编码问题。(似乎回复为8859-1。) 代码的核心: final class CsrfResponseWrapper extends AbstractResponseWrapper { ... byte[] modifyResponse(byte
final class CsrfResponseWrapper extends AbstractResponseWrapper {
...
byte[] modifyResponse(byte[] aInputResponse){
...
String originalInput = new String(aInputResponse, encoding);
String modifiedResult = addHiddenParamToPostedForms(originalInput);
result = modifiedResult.getBytes(encoding);
...
}
...
}
据我所知,字节区域和字符串区域之间的转换应该指定编码。正如你所看到的,这是在两个地方完成的。“encoding”变量的值为“UTF-8”;字符串本身的更改是标准的字符串操作(使用正则表达式),并且从不指定编码(addHiddenParamToPostedForms)
我在编码方面哪里出错了
编辑:
这是基类(抱歉,太长了):
您提供的代码似乎没有错误 你在别处干什么
- 链中是否有其他过滤器可能操纵编码/字节流,可能是过滤器位置有问题
- “编码”是修复还是动态读取请求李>
那是你的罪魁祸首。查看可以指定编码的位置。链中还有两个其他筛选器:一个用于抑制无关会话,另一个用于执行与用户登录相关的任务。两者都不会改变响应流。“编码”项已修复。没有明显的问题。你确定,如果UTF-8没有通信,通信是在UTF-8上的吗?您的包装器是否正确地转发了编码设置?非常肯定,是的。Firefox在响应头中显示UTF-8;我的JSP都保存在UTF-8中。无论我在哪里引用标记文件,我似乎都会在输出中得到“?”字符。而且,当不存在有问题的筛选器时,我可以看到阿拉伯语字符fine.FYI-基类可能是可疑的。是的,这解决了问题。在本教程中的样式之后,我修改并简化了代码:
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;
}
}