1

この質問は、Spring Security Oauth2ライブラリでやっている作業の結果です。 oauth2認証サーバーとoauth2リソースサーバーを設定しました。後者はアクセストークンに基づいて認証することを目的としています。Spring Security:リクエスト本体を2回デシリアライズする(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()がすでにこのリクエストに対して呼び出されました」というエラーが発生します。トークンの抽出にオブジェクトをデシリアライズ入力ストリーム

  • をリセットする方法を見つける

    1. :私は研究ができ、そしてこれまでのところ、私が作ってみたいくつかの可能な解決策をブレーンストーミングた

      @RequestBody

    2. のように2の代わりに、私のコントローラ内の生のリクエストオブジェクトにアクセスするだけですが、生の要求に接続されたオブジェクトをフェッチするカスタムデシリアライザを追加する方法がありますリクエストの入力ストリームを処理します。

    とにかく、これはちょっとした考えです。誰かがこれを解決する優雅な方法について考えているなら、私は大いに感謝します。

    編集:私は似ているこの質問を見つけました:Spring reading request body twice、そして最後の答えは可能な解決策を持っています(複数の入力ストリームの読み込みを許可し、フィルターチェーンを早くに作成するデコレータ要求クラスを作成しますHttpServletRequest)を呼び出します。それは実行可能だが、少し重い義務だ、私は誰も他のアイデアを持っているかどうかを確認するためにこれを残します。

  • 答えて

    0

    私はこの問題に取り組んだもう1つの質問を見つけましたが、投稿する前に私は見ていませんでした(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; 
    } 
    
    を誰もが任意のフィードバックを持っている場合にはここで

    は、私が思いついたものです

    関連する問題