Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the code analysis error. #479

Merged
merged 10 commits into from
Aug 4, 2022
1 change: 1 addition & 0 deletions changes/changes-1.6.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@
- [Optimize starters auto-configuration. (main)](https://github.com/Tencent/spring-cloud-tencent/pull/391/files)
- [Feature: format code](https://github.com/Tencent/spring-cloud-tencent/pull/394)
- [test: add PostInitPolarisSDKContextTest](https://github.com/Tencent/spring-cloud-tencent/pull/397)
- [Fix the code analysis error.](https://github.com/Tencent/spring-cloud-tencent/issues/462)
pandaapo marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ private void registerPolarisConfigPublishEvent() {

LOGGER.info(
"[SCT Config] received polaris config change event and will refresh spring context."
+ "namespace = {}, group = {}, fileName = {}",
+ " namespace = {}, group = {}, fileName = {}",
polarisPropertySource.getNamespace(),
polarisPropertySource.getGroup(),
polarisPropertySource.getFileName());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/

package com.tencent.cloud.polaris.circuitbreaker.example.xss;

import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Escape String in ResponseBody before write it into HttpResponse
*
* @author Daifu Wu
*/
@ControllerAdvice
public class XssResponseBodyAdvice implements ResponseBodyAdvice {

@Override
public boolean supports(MethodParameter methodParameter, Class aClass) {
return methodParameter.hasMethodAnnotation(ResponseBody.class) || methodParameter.getDeclaringClass().getAnnotation(ResponseBody.class) != null || methodParameter.getDeclaringClass().getAnnotation(RestController.class) != null;
}

@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if (body instanceof String) {
body = StringEscapeUtils.escapeHtml((String)body);
return body;
}
try {
if (!((Class)body.getClass().getField("TYPE").get(null)).isPrimitive()) {
Map<String, Object> map = new HashMap<>();
Field[] fields = body.getClass().getDeclaredFields();
for (Field field: fields) {
field.setAccessible(true);
Object value = field.get(body);
if (value instanceof String) {
value = StringEscapeUtils.escapeHtml((String) value);
}
map.put(field.getName(), value);
}
return map;
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
return body;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/

package com.tencent.cloud.polaris.gateway.example.callee.xss;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
* filter request aim at defending against XSS
*
* @author Daifu Wu
*/
@WebFilter(urlPatterns = "/*", filterName = "xssFilter")
@Component
public class XssFilter implements Filter {

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/

package com.tencent.cloud.polaris.gateway.example.callee.xss;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* Wrap HttpServletRequest to escape String arguments
*
* @author Daifu Wu
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] requestBody;

public XssHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
BufferedReader reader = request.getReader();
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
if (stringBuilder.length() > 0) {
String json = stringBuilder.toString();
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> map = objectMapper.readValue(json, Map.class);
map.forEach((k, v) -> {
if (v instanceof String) {
v = cleanXSS((String) v);
map.put(k, v);
}
});
json = objectMapper.writeValueAsString(map);
requestBody = json.getBytes();
}
}

/**
* Handles arguments annotated by @RequestBody
*
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}

@Override
public boolean isReady() {
return false;
}

@Override
public void setReadListener(ReadListener readListener) {

}

@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}

/**
* Handles arguments annotated by @RequestParam
*
* @param name
* @return
*/
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values != null && values.length > 0) {
String[] safeValues = new String[values.length];
for (int i = 0; i < values.length; i++) {
safeValues[i] = cleanXSS(values[i]);
}
return safeValues;
}
return values;
}

/**
* Handles arguments annotated by @PathVariable
*
* @param name
* @return
*/
@Override
public Object getAttribute(String name) {
Object value = super.getAttribute(name);
if (name.equalsIgnoreCase(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) && value != null && value instanceof Map) {
((Map) value).forEach((k, v) -> {
if (v instanceof String) {
v = cleanXSS((String) v);
((Map) value).put(k, v);
}
});
}
return value;
}

/**
* Handles arguments annotated by @RequestHeader
*
* @param name
* @return
*/
@Override
public Enumeration<String> getHeaders(String name) {
List<String> list = Collections.list(super.getHeaders(name));
list = list.stream().map((e) -> {
ObjectMapper objectMapper = new ObjectMapper();
try {
Map<String, String> map = objectMapper.readValue(e, Map.class);
map.forEach((k, v) -> {
v = cleanXSS(v);
map.put(k, v);
});
e = objectMapper.writeValueAsString(map);
} catch (JsonProcessingException e1) {
e1.printStackTrace();
}
return e;
}).collect(Collectors.toList());
return Collections.enumeration(list);
}

@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value != null) {
value = cleanXSS(value);
}
return value;
}

@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}

/**
* Escape string to defend against XSS
*
* @param value
*/
private String cleanXSS(String value) {
value = StringEscapeUtils.escapeHtml(value);
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/

package com.tencent.cloud.polaris.gateway.example.callee.xss;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
* filter request aim at defending against XSS
*
* @author Daifu Wu
*/
@WebFilter(urlPatterns = "/*", filterName = "xssFilter")
@Component
public class XssFilter implements Filter {

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
}
}
Loading