【问题标题】:How to Modify QueryParam and PathParam in Jersey 2如何在 Jersey 2 中修改 QueryParam 和 PathParam
【发布时间】:2015-10-05 00:51:14
【问题描述】:

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

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

然而,对于 Jersey 2,这不可能通过实现相同的接口来实现,因为我们不再可以 getQueryParameters() 或 getPathParameters(),而是我们只能 getUriInfo(),但是因为查询参数所以没用是不可变的。我查看了 Jersey 的 Filters and Interceptors,但不幸的是,它们仅限于访问标题和可能的 cookie。

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

是否有替代方法来过滤路径和查询参数?我有什么遗漏吗?

谢谢!

【问题讨论】:

    标签: java api rest jersey xss


    【解决方案1】:

    我在下面添加了一个适用于 Jersey 2.x 的过滤器。但是,它不会对 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<String, String> queries = request.getUriInfo().getQueryParameters();
    
            for( Map.Entry<String, List<String>> query : queries.entrySet() )
            {
                String key = query.getKey();
                List<String> 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<String, String> headers )
        {
            for( Map.Entry<String, List<String>> header : headers.entrySet() )
            {
                String key = header.getKey();
                List<String> values = header.getValue();
    
                List<String> cleanValues = new ArrayList<String>();
                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/

    【讨论】:

      【解决方案2】:

      您可以使用 ContainerRequestFilter,构造一个新的 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 模板中的参数名称替换单个路径参数,因为“setRequestUri”只允许在预资源匹配阶段。所以需要替换整个路径。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-29
        • 2020-02-22
        • 2012-06-23
        相关资源
        最近更新 更多