Spring Security: deserialize request body twice (oauth2 processing)(Spring Security:两次反序列化请求正文(OAuth2处理))
问题描述
这个问题是我使用Spring Security OAuth2库所做的一些工作的结果。我已经设置了一个OAuth2授权服务器和一个OAuth2资源服务器,后者用于基于访问令牌进行授权。
问题是,访问令牌通常在标头中传递,但我们要为其设置的大客户端希望在JSON请求正文中传递访问令牌。您可以使用一个接口来设置自定义访问令牌提取,但它看起来如下所示:
public interface TokenExtractor {
/**
 * Extract a token value from an incoming request without authentication.
 * 
 * @param request the current ServletRequest
 * @return an authentication token whose principal is an access token (or null if there is none)
 */
Authentication extract(HttpServletRequest request);
}
因此,据我所知,我只能访问原始HTTPServletRequest,我需要从它反序列化请求并提取访问令牌。
更复杂的是,请求体还包含处理所需的其他参数,因此我希望将其反序列化为DTO类,并将其传递到控制器中,如下所示:
@RequestMapping("/oauth/someresource")
@Transactional
public Map<String, String> resource(@AuthenticationPrincipal UserDetails userDetails,
                                     @RequestBody ClientRequestDto clientRequestDto) {
// Do some processing based on the request dto
}
我尝试在令牌提取程序中手动反序列化请求,但随后收到错误消息"java.lang.IlLegalStateException:已为此请求调用了getReader()"。
我正在集思广益,想出一些我可以研究的可能的解决方案,到目前为止,我已经想出了:
- 找到重置输入流的方法
 - 在令牌提取程序中反序列化对象,将其附加到原始请求对象,然后只访问控制器中的原始请求对象,而不是使用@RequestBody
 - 与2类似,但找到了添加自定义反序列化程序的方法,该反序列化程序获取附加到原始请求的对象,而不是处理请求的输入流。
 
编辑:我确实发现了这个类似的问题:Spring reading request body twice,而上一个答案确实有一个可能的解决方案(创建一个允许多个输入流读取的修饰器请求类,并在包装HttpServletRequest的筛选器链的早期创建一个筛选器)。这似乎是可行的,但有点繁重,所以我把这件事留下来看看是否有人还有其他想法。
推荐答案
所以我最终找到了另一个问题,这个问题是我在发帖之前没有看到的(How can I read request body multiple times in Spring 'HandlerMethodArgumentResolver'?)。那个人还建议围绕HttpServletRequest创建一个装饰器,所以我改编了http://www.myjavarecipes.com/how-to-read-post-request-data-twice-in-spring/中的信息,增加了对大型请求的保护。
这是我想出来的,以防任何人有任何反馈:
public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
// We include a max byte size to protect against malicious requests, since this all has to be read into memory
public static final Integer MAX_BYTE_SIZE = 1_048_576; // 1 MB
private String _body;
public MultiReadHttpServletRequest(HttpServletRequest request) throws IOException {
    super(request);
    _body = "";
    InputStream bounded = new BoundedInputStream(request.getInputStream(), MAX_BYTE_SIZE);
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(bounded));
    String line;
    while ((line = bufferedReader.readLine()) != null){
        _body += line;
    }
}
@Override
public ServletInputStream getInputStream() throws       IOException {
    final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(_body.getBytes());
    return new ServletInputStream() {
        public int read() throws IOException {
            return byteArrayInputStream.read();
        }
        @Override
        public boolean isFinished() {
            return byteArrayInputStream.available() == 0;
        }
        @Override
        public boolean isReady() {
            return true;
        }
        @Override
        public void setReadListener(ReadListener readListener) {
        }
    };
}
@Override
public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
我使用了以下配置:
    @Bean
FilterRegistrationBean multiReadFilter() {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    MultiReadRequestFilter multiReadRequestFilter = new MultiReadRequestFilter();
    registrationBean.setFilter(multiReadRequestFilter);
    registrationBean.setOrder(SecurityProperties.DEFAULT_FILTER_ORDER - 2);
    registrationBean.setUrlPatterns(Sets.newHashSet("/path/here"));
    return registrationBean;
}
                        这篇关于Spring Security:两次反序列化请求正文(OAuth2处理)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Spring Security:两次反序列化请求正文(OAuth2处理)
				
        
 
            
        - 未找到/usr/local/lib 中的库 2022-01-01
 - 在 Java 中,如何将 String 转换为 char 或将 char 转换 2022-01-01
 - GC_FOR_ALLOC 是否更“严重"?在调查内存使用情况时? 2022-01-01
 - 将 Java Swing 桌面应用程序国际化的最佳实践是什么? 2022-01-01
 - 如何指定 CORS 的响应标头? 2022-01-01
 - 获取数字的最后一位 2022-01-01
 - java.lang.IllegalStateException:Bean 名称“类别"的 BindingResult 和普通目标对象都不能用作请求属性 2022-01-01
 - Eclipse 的最佳 XML 编辑器 2022-01-01
 - 转换 ldap 日期 2022-01-01
 - 如何使 JFrame 背景和 JPanel 透明且仅显示图像 2022-01-01
 
						
						
						
						
						
				
				
				
				