自定义了一个过滤器过滤restapi的数据,但是在重新request 时报错!

自定义了一个过滤器过滤restapi的数据,但是在重新request 时报错!,错误信息:18:30:08.122 WARN o.s.s.o.p.endpoint.TokenEndpoint - Handling error: InvalidRequestException, Missing grant type

麻烦贴一下错误堆栈?

场景是这样,我定义了一个过滤器组件,代码如下:image
image
利用postman 进行测试时,出现18:30:08.122 WARN o.s.s.o.p.endpoint.TokenEndpoint - Handling error: InvalidRequestException, Missing grant type的错误!

我猜可能是RequestWrapper时丢失了RestAPI需要的header信息。 检查一下wrapper前和wrapper后的header 信息是否一致

好的,我检查一下,我在修改request时,只是使用request.getInputStream()进行参数修改,应该不会涉及到header信息!

image

错误提示比较明显 ,确认一下header中是否传递了 grant_type

image

如果不重写requset.getInputStream,是没问题的!

哦, grant_type 应该是在 body 中,可能是wrapper有问题,导致取不到body或body内容变化。能贴出完整的 wrapper定义吗。

protected static class RestSecurityRequestWrapper extends HttpServletRequestWrapper {
private byte[] body; // 报文
private final Logger log = LoggerFactory.getLogger(RestSecurityRequestWrapper.class);

    public RestSecurityRequestWrapper(HttpServletRequest request) throws Exception {
        super(request);
        //替换报文内容
        body = InputStreamToByte(request.getInputStream());
        String bodyStr = new String(body);
        body = bodyStr.getBytes();
    }

    /**
     * 流转 字节数组
     *
     * @param is
     * @return
     * @throws IOException
     */
    private byte[] InputStreamToByte(InputStream is) throws IOException {
        ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int ch;
        while ((ch = is.read(buffer)) != -1) {
            bytestream.write(buffer, 0, ch);
        }
        byte data[] = bytestream.toByteArray();
        bytestream.close();
        return data;
    }

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

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {

            @Override
            public boolean isFinished() {
                return bais.available() == 0;
            }

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

            @Override
            public void setReadListener(ReadListener readListener) {

            }

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

Spring security 获取grant_type时是通过 request.getParameter 来获取的,你目前的wrapper方式封装不完整,会丢失form参数。
要实现restapi拦截处理,有两种方式:

  1. 继续完善现在的wrapper,覆盖并实现getParameter 方法。
  2. 扩展CUBA的restapi 身份认证bean:com.haulmont.addon.restapi.api.auth.CubaUserAuthenticationProvider, 实现方法:authenticate(Authentication authentication) 。在这个方法中对密码进行额外处理。

建议使用第二种方式,因为第一种方式涉及到了更多Spring 框架技术细节,实现成本较高。

1 个帖子被拆分到新主题:如何拦截RestAPI调用