java list%3c%3e对象_java - 使用servlet过滤器从发布的数据中删除表单参数 - 堆栈内存溢出...

途径

代码遵循正确的方法:

在wrapRequest() ,它实例化HttpServletRequestWrapper并覆盖触发请求解析的4个方法:

public String getParameter(String name)

public Map getParameterMap()

public Enumeration getParameterNames()

public String[] getParameterValues(String name)

doFilter()方法使用包装请求调用过滤器链,这意味着后续过滤器和目标servlet(URL映射)将提供包装请求。

问题

在底层“原始请求”上调用4个方法中的任何一个getParameterXXX()方法会触发所有请求参数的隐式解析(通过服务器内部方法,如Request.parseRequestParameters or parsePameters )。 这4种方法是触发此类解析的唯一方法。

在请求被包装之前,在parseRequest() ,您的代码在底层请求上调用此类方法:request.getParameterNames(); request.getParameterValues(paramName);

您需要控制解析逻辑。 从输入流中读取原始字节并进行自己的URL解码过于复杂 - 这意味着要替换大量紧密耦合的服务器代码。 相反,最简单的方法是只替换执行实际URL解码的方法。 这意味着您可以保留prev节中提到的request.getParameterXXX调用。

不确定您正在托管ColdFusion的服务器,但以下描述基于Glassfish / Tomcat,但可以进行调整。 这篇文章的底部是Glassfish的内部请求解析方法(Tomcat的修改版本)。 JD-decompiler对于将.class文件转换为.java的修补非常有用。

找到进行URL解码的类(对于Glassfish,这是来自grizzly-utils.jar com.sun.grizzly.util.http.Parameters ,如下所示,对于Tomcat,这是来自tomcat-coyote.jar org.apache.tomcat.util.http.Parameters tomcat-coyote.jar )

将整个源代码复制到一个新类somepackage.StrippedParameters

找到解码参数值的代码行(如下所示: value = urlDecode(this.tmpValue) )

更改此代码,以便仅在参数名称与所需参数匹配时进行解码:if (decodeName) name = urlDecode(this.tmpName); else name = this.tmpName.toString(); // // !! THIS IF STATEMENT ADDED TO ONLY DECODE DESIRED PARAMETERS, // !! OTHERS ARE STRIPPED: // if ("XMLContent".equals(name)) { String value; String value; if (decodeValue) value = urlDecode(this.tmpValue); else { value = this.tmpValue.toString(); } try { addParameter(name, value); } catch (IllegalStateException ise) { logger.warning(ise.getMessage()); break; } }

现在是棘手的部分:在URL解码发生之前,使用您的类StrippedParmeters替换默认类Parameters 。 获取参数后,将它们复制回容器类。 GlassFish的复制方法parseRequestParameters到您实现了HttpServletRequestWrapper的(Tomcat的,相应的方法是parseParameters类org.apache.catalina.connector.Request在catalina.jar )

替换这一行:Parameters parameters = this.coyoteRequest.getParameters();

有:Parameters parameters = new somepackage.StrippedParameters();

在方法的底部,添加以下内容:Parameters coyoteParameters = this.coyoteRequest.getParameters(); for (String paramName : parameters.getParameterNames()) { String paramValue = parameters.getParameterValue(paramName); coyoteParameters.addParameter(paramName, paramValue); }

Glassfish容器代码 - Tomcat的修改版本,Grizzly取代Coyote(Catalina Servlet Engine仍然指Coyote对象,但它们是像Coyote一样被嘲笑的Grizzly实例)

package org.apache.catalina.connector;

....

public class Request implements HttpRequest, HttpServletRequest {

....

protected com.sun.grizzly.tcp.Request coyoteRequest;

....

// This is called from the 4 methods named 'getParameterXXX'

protected void parseRequestParameters() {

Parameters parameters = this.coyoteRequest.getParameters();

parameters.setLimit(getConnector().getMaxParameterCount());

String enc = getCharacterEncoding();

this.requestParametersParsed = true;

if (enc != null) {

parameters.setEncoding(enc);

parameters.setQueryStringEncoding(enc);

} else {

parameters.setEncoding("ISO-8859-1");

parameters.setQueryStringEncoding("ISO-8859-1");

}

parameters.handleQueryParameters();

if ((this.usingInputStream) || (this.usingReader)) {

return;

}

if (!getMethod().equalsIgnoreCase("POST")) {

return;

}

String contentType = getContentType();

if (contentType == null) {

contentType = "";

}

int semicolon = contentType.indexOf(';');

if (semicolon >= 0)

contentType = contentType.substring(0, semicolon).trim();

else {

contentType = contentType.trim();

}

if ((isMultipartConfigured()) && ("multipart/form-data".equals(contentType))) {

getMultipart().init();

}

if (!"application/x-www-form-urlencoded".equals(contentType)) {

return;

}

int len = getContentLength();

if (len > 0) {

int maxPostSize = ((Connector)this.connector).getMaxPostSize();

if ((maxPostSize > 0) && (len > maxPostSize)) {

log(sm.getString("coyoteRequest.postTooLarge"));

throw new IllegalStateException("Post too large");

}

try {

byte[] formData = getPostBody();

if (formData != null)

parameters.processParameters(formData, 0, len);

} catch (Throwable t) {

}

}

}

}

package com.sun.grizzly.tcp;

import com.sun.grizzly.util.http.Parameters;

public class Request {

....

private Parameters parameters = new Parameters();

....

public Parameters getParameters() {

return this.parameters;

}

}

package com.sun.grizzly.util.http;

public class Parameters {

....

public void processParameters(byte[] bytes, int start, int len) {

processParameters(bytes, start, len, getCharset(this.encoding));

}

public void processParameters(byte[] bytes, int start, int len, Charset charset) {

if (debug > 0) {

try {

log(sm.getString("parameters.bytes", new String(bytes, start, len, "ISO-8859-1")));

} catch (UnsupportedEncodingException e) {

logger.log(Level.SEVERE, sm.getString("parameters.convertBytesFail"), e);

}

}

int decodeFailCount = 0;

int end = start + len;

int pos = start;

while (pos < end) {

int nameStart = pos;

int nameEnd = -1;

int valueStart = -1;

int valueEnd = -1;

boolean parsingName = true;

boolean decodeName = false;

boolean decodeValue = false;

boolean parameterComplete = false;

do {

switch (bytes[pos]) {

case 61:

if (parsingName) {

nameEnd = pos;

parsingName = false;

pos++; valueStart = pos;

} else {

pos++;

}

break;

case 38:

if (parsingName) {

nameEnd = pos;

} else {

valueEnd = pos;

}

parameterComplete = true;

pos++;

break;

case 37:

case 43:

if (parsingName)

decodeName = true;

else {

decodeValue = true;

}

pos++;

break;

default:

pos++;

}

} while ((!parameterComplete) && (pos < end));

if (pos == end) {

if (nameEnd == -1)

nameEnd = pos;

else if ((valueStart > -1) && (valueEnd == -1)) {

valueEnd = pos;

}

}

if ((debug > 0) && (valueStart == -1)) {

try {

log(sm.getString("parameters.noequal", Integer.valueOf(nameStart),

Integer.valueOf(nameEnd),

new String(bytes, nameStart, nameEnd - nameStart, "ISO-8859-1")));

} catch (UnsupportedEncodingException e) {

logger.log(Level.SEVERE, sm.getString("parameters.convertBytesFail"), e);

}

}

if (nameEnd <= nameStart) {

if (logger.isLoggable(Level.INFO)) {

if (valueEnd >= nameStart)

try {

new String(bytes, nameStart, valueEnd - nameStart, "ISO-8859-1");

} catch (UnsupportedEncodingException e) {

logger.log(Level.SEVERE,

sm.getString("parameters.convertBytesFail"), e);

} else {

logger.fine(sm.getString("parameters.invalidChunk",

Integer.valueOf(nameStart), Integer.valueOf(nameEnd), null));

}

}

} else {

this.tmpName.setCharset(charset);

this.tmpValue.setCharset(charset);

this.tmpName.setBytes(bytes, nameStart, nameEnd - nameStart);

this.tmpValue.setBytes(bytes, valueStart, valueEnd - valueStart);

if (debug > 0)

try {

this.origName.append(bytes, nameStart, nameEnd - nameStart);

this.origValue.append(bytes, valueStart, valueEnd - valueStart);

}

catch (IOException ioe) {

logger.log(Level.SEVERE, sm.getString("parameters.copyFail"), ioe);

}

try

{

String name;

String name;

if (decodeName)

name = urlDecode(this.tmpName);

else

name = this.tmpName.toString();

String value;

String value;

if (decodeValue)

value = urlDecode(this.tmpValue);

else {

value = this.tmpValue.toString();

}

try

{

addParameter(name, value);

}

catch (IllegalStateException ise)

{

logger.warning(ise.getMessage());

break;

}

} catch (IOException e) {

decodeFailCount++;

if ((decodeFailCount == 1) || (debug > 0)) {

if (debug > 0) {

log(sm.getString("parameters.decodeFail.debug", this.origName.toString(), this.origValue.toString()), e);

}

else if (logger.isLoggable(Level.INFO)) {

logger.log(Level.INFO, sm.getString("parameters.decodeFail.info", this.tmpName.toString(), this.tmpValue.toString()), e);

}

}

}

this.tmpName.recycle();

this.tmpValue.recycle();

if (debug > 0) {

this.origName.recycle();

this.origValue.recycle();

}

}

}

if ((decodeFailCount > 1) && (debug <= 0))

logger.info(sm.getString("parameters.multipleDecodingFail", Integer.valueOf(decodeFailCount)));

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值