如何在Jersey 2中修改QueryParam和PathParam

我正在尝试过滤/修改Post和Put调用,以确保从HTML和JS代码中过滤用户提供的所有参数,以防止XSS攻击。 我想确保这是在API级别实现的,因此无论使用何种客户端,它都将受到保护。

使用Jersey 1.x,可以通过实现ContainerRequestFilter并在与请求的servlet匹配之前修改request.getQueryParameters()来实现。 示例: http : //codehustler.org/blog/jersey-cross-site-scripting-xss-filter-for-java-web-apps/

然而,对于Jersey 2,由于我们不能再使用getParameters()或getPathParameters(),因此无法通过实现相同的接口实现这一点,但是我们只能使用getUriInfo(),但由于查询参数是不可变的,因此它是无用的。 我查看了Jersey的filter和拦截器,但遗憾的是它们只能访问标题和Cookie。

我花了很多时间研究,但我找不到我想要的东西。

是否有另一种方法来过滤路径和查询参数? 有什么我想念的吗?

谢谢!

我在下面添加了一个适用于Jersey 2.x的filter。 但是,它没有执行Cookie的XSS修复,因为我还没有找到修改它们的方法。

需要注意的是,这需要与POJO属性上的@SafeHtml结合使用,以便清理这些值。

@PreMatching public class XSSFilter implements ContainerRequestFilter { /** * @see ContainerRequestFilter#filter(ContainerRequest) */ @Override public void filter( ContainerRequestContext request ) { cleanQueryParams( request ); cleanHeaders( request.getHeaders() ); } /** * Replace the existing query parameters with ones stripped of XSS vulnerabilities * @param request */ private void cleanQueryParams( ContainerRequestContext request ) { UriBuilder builder = request.getUriInfo().getRequestUriBuilder(); MultivaluedMap queries = request.getUriInfo().getQueryParameters(); for( Map.Entry> query : queries.entrySet() ) { String key = query.getKey(); List values = query.getValue(); builder.replaceQueryParam( key ); for( String value : values ) { builder.replaceQueryParam( key, Utils.stripXSS( value ) ); } } request.setRequestUri( builder.build() ); } /** * Replace the existing headers with ones stripped of XSS vulnerabilities * @param headers */ private void cleanHeaders( MultivaluedMap headers ) { for( Map.Entry> header : headers.entrySet() ) { String key = header.getKey(); List values = header.getValue(); List cleanValues = new ArrayList(); for( String value : values ) { cleanValues.add( Utils.stripXSS( value ) ); } headers.put( key, cleanValues ); } } } 

stripXSS函数如下:

 /** * Strips any potential XSS threats out of the value * * @param value * @return */ public static String stripXSS( String value ) { return stripXSS( value, Whitelist.none() ); } /** * Strips any potential XSS threats out of the value excluding * the white listed HTML * * @param value * @param whitelist * @return */ public static String stripXSS( String value, Whitelist whitelist ) { if( StringUtils.isBlank( value ) ) return value; // Use the ESAPI library to avoid encoded attacks. value = ESAPI.encoder().canonicalize( value ); // Avoid null characters value = value.replaceAll("\0", ""); // Clean out HTML Document.OutputSettings outputSettings = new Document.OutputSettings(); outputSettings.escapeMode( EscapeMode.xhtml ); outputSettings.prettyPrint( false ); value = Jsoup.clean( value, "", whitelist, outputSettings ); return value; } 

还更新了原帖: http : //codehustler.org/blog/jersey-cross-site-scripting-xss-filter-for-java-web-apps/

您可以使用ContainerRequestFilter,构造一个新URI(基于现有URI),并通过setRequestUri方法在ContainerRequestContext中设置URI。

 @PreMatching public class MyFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) throws IOException { UriBuilder builder = requestContext.getUriInfo().getRequestUriBuilder(); // Replace a query param builder.replaceQueryParam("foo", "bar"); // Remove a query param builder.replaceQueryParam("baz"); // Replace path builder.replacePath("newPath"); requestContext.setRequestUri(builder.build()); } } 

然而,通过这种方法,我还没有找到一种方法来替换匹配的Jersey资源的URI模板中基于param名称的单个路径参数,因为“setRequestUri”仅允许在资源前匹配阶段。 因此需要更换整个路径。