코드 변환 문 제 를 해결 하 는 과정 을 기록 합 니 다.-springboot tomcat 소스 코드 를 수정 합 니 다.%변환 되 지 않 아 파 라 메 터 를 받 을 수 없습니다.
11772 단어 SpringCloud구조 노트
자바 로 PHP 프로젝트 를 재 구성 합 니 다.예전 에는 인터페이스 디자인 이 합 리 적 이지 않 았 기 때문에 다양한 매개 변수 가 날 아 다 녔 습 니 다.자바 코드 를 점차적으로 대체 하고 온라인 업무 에 영향 을 주지 않 기 위해 서 입 니 다.첫 번 째 단 계 는 매개 변수 와 인터페이스 방식 이 변 하지 않 는 다 는 것 을 결정 하 는 것 도 이 문 제 를 일 으 켰 다.
문제 가 생기다
같은 인터페이스:
go->자바 와 클 라 이언 트->자바,Content-Type 은 모두 application/x-www-form-urlencoded 이지 만 클 라 이언 트 가 인 자 를 바 꾸 었 지만 유일한%는 바 꾸 지 않 았 습 니 다.
예 를 들 어{"param":"%"}정확 한 코드 는%7B%22param%22%3A%22%25%22%7D 이지 만%7B%22param%22%3A%22%22%7D 로 바 뀌 었 습 니 다.
배경 에서 데 이 터 를 받 지 못 합 니 다.
3.해결 방안:
tomcat 에 로그 오류 가 발생 합 니 다(debug 모드 를 켜 야 볼 수 있 습 니 다):org.apache.tomcat.util.http.Parameters:173 [http-nio-20977-exec-1] - Character decoding failed. Parameter
첫 번 째:클 라 이언 트(안 드 로 이 드)는 코드 를 수정 하고 모든 데 이 터 를 전의 해 야 합 니 다.이것 은 클 라 이언 트 를 강제로 업그레이드 해 야 합 니 다(포기)
두 번 째:자바 서버 tomcat 소스 코드 수정
Parameters 라 는 클래스 에 들 어가 코드 를 연구 한 결과 processParameters 라 는 방법 에서%가 분석 되 지 않 았 습 니 다.코드 는 다음 과 같 습 니 다.
private void processParameters(byte bytes[], int start, int len, Charset charset) {
if(log.isDebugEnabled()) {
log.debug(sm.getString("parameters.bytes",
new String(bytes, start, len, DEFAULT_BODY_CHARSET)));
}
int decodeFailCount = 0;
int pos = start;
int end = start + len;
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 '=':
if (parsingName) {
// Name finished. Value starts from next character
nameEnd = pos;
parsingName = false;
valueStart = ++pos;
} else {
// Equals character in value
pos++;
}
break;
case '&':
if (parsingName) {
// Name finished. No value.
nameEnd = pos;
} else {
// Value finished
valueEnd = pos;
}
parameterComplete = true;
pos++;
break;
case '%':
case '+':
// Decoding required
if (parsingName) {
decodeName = true;
} else {
decodeValue = true;
}
pos ++;
break;
default:
pos ++;
break;
}
} while (!parameterComplete && pos < end);
if (pos == end) {
if (nameEnd == -1) {
nameEnd = pos;
} else if (valueStart > -1 && valueEnd == -1){
valueEnd = pos;
}
}
if (log.isDebugEnabled() && valueStart == -1) {
log.debug(sm.getString("parameters.noequal",
Integer.valueOf(nameStart), Integer.valueOf(nameEnd),
new String(bytes, nameStart, nameEnd-nameStart, DEFAULT_BODY_CHARSET)));
}
if (nameEnd <= nameStart ) {
if (valueStart == -1) {
// &&
if (log.isDebugEnabled()) {
log.debug(sm.getString("parameters.emptyChunk"));
}
// Do not flag as error
continue;
}
// &=foo&
UserDataHelper.Mode logMode = userDataLog.getNextMode();
if (logMode != null) {
String extract;
if (valueEnd > nameStart) {
extract = new String(bytes, nameStart, valueEnd - nameStart,
DEFAULT_BODY_CHARSET);
} else {
extract = "";
}
String message = sm.getString("parameters.invalidChunk",
Integer.valueOf(nameStart),
Integer.valueOf(valueEnd), extract);
switch (logMode) {
case INFO_THEN_DEBUG:
message += sm.getString("parameters.fallToDebug");
//$FALL-THROUGH$
case INFO:
log.info(message);
break;
case DEBUG:
log.debug(message);
}
}
setParseFailedReason(FailReason.NO_NAME);
continue;
// invalid chunk - it's better to ignore
}
tmpName.setBytes(bytes, nameStart, nameEnd - nameStart);
if (valueStart >= 0) {
tmpValue.setBytes(bytes, valueStart, valueEnd - valueStart);
} else {
tmpValue.setBytes(bytes, 0, 0);
}
// Take copies as if anything goes wrong originals will be
// corrupted. This means original values can be logged.
// For performance - only done for debug
if (log.isDebugEnabled()) {
try {
origName.append(bytes, nameStart, nameEnd - nameStart);
if (valueStart >= 0) {
origValue.append(bytes, valueStart, valueEnd - valueStart);
} else {
origValue.append(bytes, 0, 0);
}
} catch (IOException ioe) {
// Should never happen...
log.error(sm.getString("parameters.copyFail"), ioe);
}
}
try {
String name;
String value;
if (decodeName) {
urlDecode(tmpName);
}
tmpName.setCharset(charset);
name = tmpName.toString();
if (valueStart >= 0) {
if (decodeValue) {
urlDecode(tmpValue);
}
tmpValue.setCharset(charset);
value = tmpValue.toString();
} else {
value = "";
}
try {
addParameter(name, value);
} catch (IllegalStateException ise) {
// Hitting limit stops processing further params but does
// not cause request to fail.
UserDataHelper.Mode logMode = maxParamCountLog.getNextMode();
if (logMode != null) {
String message = ise.getMessage();
switch (logMode) {
case INFO_THEN_DEBUG:
message += sm.getString(
"parameters.maxCountFail.fallToDebug");
//$FALL-THROUGH$
case INFO:
log.info(message);
break;
case DEBUG:
log.debug(message);
}
}
break;
}
} catch (IOException e) {
setParseFailedReason(FailReason.URL_DECODING);
decodeFailCount++;
if (decodeFailCount == 1 || log.isDebugEnabled()) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("parameters.decodeFail.debug",
origName.toString(), origValue.toString()), e);
} else if (log.isInfoEnabled()) {
UserDataHelper.Mode logMode = userDataLog.getNextMode();
if (logMode != null) {
String message = sm.getString(
"parameters.decodeFail.info",
tmpName.toString(), tmpValue.toString());
switch (logMode) {
case INFO_THEN_DEBUG:
message += sm.getString("parameters.fallToDebug");
//$FALL-THROUGH$
case INFO:
log.info(message);
break;
case DEBUG:
log.debug(message);
}
}
}
}
}
tmpName.recycle();
tmpValue.recycle();
// Only recycle copies if we used them
if (log.isDebugEnabled()) {
origName.recycle();
origValue.recycle();
}
}
if (decodeFailCount > 1 && !log.isDebugEnabled()) {
UserDataHelper.Mode logMode = userDataLog.getNextMode();
if (logMode != null) {
String message = sm.getString(
"parameters.multipleDecodingFail",
Integer.valueOf(decodeFailCount));
switch (logMode) {
case INFO_THEN_DEBUG:
message += sm.getString("parameters.fallToDebug");
//$FALL-THROUGH$
case INFO:
log.info(message);
break;
case DEBUG:
log.debug(message);
}
}
}
}
트 레이스 byte 배열 의 출처 는 Request 류 에서 byte 배열 이 최종 적 으로 postdata 에서 온 것 을 발 견 했 기 때문에 먼저 postdata 를 전의 하여 교체 합 니 다.
if(null != postData){
String param = new String(postData);
if(param.contains("%%")){
param = param.replace("%%","%25%");
postData = param.getBytes();
len += 2;
}
}
Request 클래스 의 3212 줄 에 이 코드 를 추가 하면 실행 중 문제 가 해결 되 지 않 습 니 다.첫 번 째 요청 은 post Data 가 비어 있 으 면 이 코드 에 들 어가 지 않 기 때 문 입 니 다.formData 는 post Data 가 비어 있 는 것 을 발견 하면 body 에서 데 이 터 를 가 져 오기 때문에 해결 되 지 않 았 습 니 다.
연구 코드 는 formData 의 데이터 만 바 꿀 수 있 음 을 발견 했다.
if(null != formData){
String param = new String(formData);
if(param.contains("%%")){
param = param.replace("%%","%25%");
formData = param.getBytes();
len += 2;
}
}
완벽 한 해결!!
글 의 문 제 를 발견 하면 메 시 지 를 남 겨 주세요.제 가 제일 먼저 대답 하 겠 습 니 다.감사합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
SpringCloud OAuth2 + JWT 인증 인증(一) 인증 서버Spring Cloud oAuth2(1) 라이센스 서버 구축 및 액세스 Spring Cloud oAuth2(2) 리소스 서버 구축 및 테스트 SpringCloud OAuth2 + JWT 인증 인증(一) 인증 서버 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.