【问题标题】:XSS interceptor for Jax-rs using Apache CXF使用 Apache CXF 的 Jax-rs 的 XSS 拦截器
【发布时间】:2023-12-02 01:04:01
【问题描述】:

我正在使用 CXF 处理 XSS 拦截器任务。根据项目依赖项,我不能使用 Jersey。而且我看不到任何使用拦截器或过滤器从请求中更改表单数据(表单参数)的方法。 我从文档中发现我们无法使用 cxf 修改请求参数(不包括查询参数),尽管 jersey 提供了一种修改这些参数的方法。

但在拦截器中,我也看不到任何修改表单参数的方法。我可以看到很多修改标头/查询参数的示例。但看不到任何修改请求参数的示例。任何人都可以提供一些帮助并为此提供示例代码示例。

现在我正在检查 ReaderInterceptor。但它也不是像调用拦截器那样调用。如果您对此也有任何想法,请告诉我。

【问题讨论】:

    标签: jax-rs cxf xss interceptor


    【解决方案1】:

    您必须定义一个拦截器以在您的业务服务处理入站消息之前捕获它们,提取表单参数,传递 XSS 过滤器并根据您的需要更新参数或中止处理。

    拦截器

    这是一个使用 CXF AbstractPhaseInterceptor 的基本示例

    public class XSSInterceptor extends AbstractPhaseInterceptor<Message> {
    
        public XSSInterceptor () {
            super(Phase.INVOKE);
        }
    
        @Override
        public void handleMessage(Message message) throws Fault {
    
            // filter only application/x-www-form-urlencoded
            String contentType = (String)message.get(Message.CONTENT_TYPE);
            if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)){ /
    
                // message parts
                List list = message.getContent(List.class); 
                for (int i = 0; i < list.size();i++){
    
                    //get the parameter map
                    MultivaluedMap<String, String> params = (MultivaluedMap<String, String> )list.get(i);
                    for(String param: params.keySet()){
                        List<String> values = params.get(param);
    
                        //XSS filter here. Update the value list if needed or abort the request
                        List<String> updatedValues = xssFilter(values);
                        params.put(param, updatedValues);
                    }
                }
            }
    
        }
        @Override
        public void handleFault(Message messageParam) {
        }
     }
    

    CXF 配置

    <bean id="xssInterceptor" class="XSSInterceptor" />
    <cxf:bus>
        <cxf:inInterceptors>
            <ref bean="xssInterceptor"/>
       </cxf:inInterceptors>
    </cxf:bus> 
    

    此配置将适用于这样的服务

    @POST
    @Path("/form")
    @Consumes({MediaType.APPLICATION_FORM_URLENCODED})
    public Response form(MultivaluedMap<String, String> params) throws WebApplicationException;
    

    *RequestContextFilter

    您也可以使用 RequestContextFilter

     public class CustomRequestFilter implements ContainerRequestFilter {
       public void filter(ContainerRequestContext context) {
        Message m = JAXRSUtils.getCurrentMessage(); 
        //XSS filter here. In the same way the above intercerceptor
        // finally use context.abortWith(Response) if you need to block the request 
    

    弹簧配置

    <bean id="customRequestFilter" class="com.CustomRequestFilter" />
    
     <!-- Add filters to provider zone in JAX-RS server-->
     <bean id="myRestServer" class="org.apache.cxf.jaxrs.JAXRSServerFactoryBean" lazy-init="false" init-method="create">
        ...
         <property name="providers">
             <list>
                  <ref bean="customRequestFilter" />
             </list>
         </property>
    

    【讨论】:

    • 感谢您的帮助 XSSInterceptor 工作正常,但我们无法使用 CustomRequestFilter 更新表单参数。我试过了,但失败了。
    • 嗨 @pedrofb,如果我们将休息服务的 MediaType 从 APPLICATION_FORM_URLENCODED 更改为 Application_json,您能帮帮我吗?因为在我的情况下,我们的 UI 将仅发送 Application_json 请求,在这种情况下它会失败。为此我需要做哪些改变
    • 使用application/json 你必须处理传入的流,而不是参数。用message.getContent(InputStream.class)获取,消费处理字符串数据,用message.getExchange().setContent(analyzedStream)设置新内容
    【解决方案2】:

    @PreMatching 公共类 XSSInterceptor 扩展 AbstractPhaseInterceptor {

    private XSSRequestWrapper xssRequestWrapper;
    
    public XSSInterceptor() {
        super(Phase.POST_LOGICAL);
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public void handleMessage(Message message) throws Fault {
        HttpServletRequest httpRequest = (HttpServletRequest) message.get("HTTP.REQUEST");
        xssRequestWrapper = new XSSRequestWrapper(httpRequest);
    
        // filter only application/x-www-form-urlencoded
        String contentType = (String) message.get(Message.CONTENT_TYPE);
        if (MediaType.APPLICATION_FORM_URLENCODED.equalsIgnoreCase(contentType)
                || MediaType.APPLICATION_JSON.equalsIgnoreCase(contentType)) {
            // message parts
            List list = message.getContent(List.class);
            String jsonString = "";
    
            for (int i = 0; i < list.size(); i++) {
                jsonString = list.get(i).toString();
            }
    
            Response response = Response.status(Response.Status.ACCEPTED)
                    .entity(xssRequestWrapper.stripXSS(jsonString)).build();
    
            message.getExchange().put(Response.class, response);
        }
    }
    

    }

    此拦截器将适用于以下 api 操作:- @邮政 @Path("details2") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) 公共响应 getPersonalInfoDetails2(String jsonString) 抛出 DataNotFoundException;

    【讨论】:

      最近更新 更多