0

私には興味深い問題があります (少なくとも、私の現在の観点からは問題です)。

インターフェイスを公開している RESTful Web サービスがあります。私たちの環境では、アノテーションを使用してリクエストハンドラーを装飾します。

@RequiredTokenType("Binary")
public String getRecordInfo(HttpServletRequest request) {
    String recordInfo = null;

    final String methodName = "getRecordInfo()";
    _log.debug("{}: received request", methodName);

    // validate the request information
    ValidationUtils.validateAcceptHeader(request, MimeConstants.getContentType());

    .   .   .
    .   .   .

    return recordInfo;
}

CXF インターセプター/アスペクト (Spring AOP) をハンドラーの前に (上記のように) 実行し、HttpServletRequest でトークンの種類を確認する必要があります。トークン タイプ (またはハンドラーを装飾しているその他の属性) がアノテーションで指定されたタイプでない場合、実行を停止し、HTTP ステータス 400 (不正な要求) を返します。上記のような約 20 の要求ハンドラーがあります。

ここで私が直面している問題は、アスペクトに基づいたスプリング AOP を作成した後 (以下のように)、getRecordInfo() が実行される前にリクエストをキャッチできますが、400 を返そうとすると (または) 例外をスローしようとすると、HTTPクライアントにはまだ 200 が表示されます -

public void validateRequest(ProceedingJoinPoint joinPoint,
                            HttpServletRequest httpRequest,
                            RequiredTokenType tokenType) throws Throwable {

    final String methodName = "validateRequest()";
    _logger.info("{}: Entered, Thread Id: {}", methodName, "" + Thread.currentThread().getId());

    // Extract the *REQUIRED* headers from the request ...
    final String tokenData = httpRequest.getHeader(HEADER_TOKEN_DATA);

    if (tokenData == null || tokenData.trim().length() < MIN_POSSIBLE_TOKEN_SIZE) {
        // Error condition .... return (400 Bad Request)
        _logger.info("{}: Invalid token. The HTTP request is rejected in lack of a valid token.");

        throw new MissingTokenException(HttpStatus.BAD_REQUEST,
                                        ErrorCode.BAD_REQUEST,
                                        "Token is missing from the request.");
    }

    ValidityToken extractedTokenFromRequest = ValidityToken.initializeFromBase64(tokenData);

    // Get the type of the token this request must include ...
    String decoratedTokenType = tokenType.value();
    _logger.debug("{}: Token Type Required: ", methodName, decoratedTokenType);

    if (! extractedTokenFromRequest.getTypeName().equals(decoratedTokenType)) {
        // Error condition .... return (400).
        _logger.info("{}: {}",
                     methodName,
                     "The token in the request mismatches the type specified in RequiredTokenType handler. 400 Bad Request.");
        throw new TokenTypeMismatchException(HttpStatus.BAD_REQUEST,
                                             ErrorCode.BAD_REQUEST,
                                             "Token type doesn't match.");
    }

    // More validations on extractedTokenFromRequest
    .   .   .
    .   .   .

    // Continue with the actual business logic if correct token is included ...
    joinPoint.proceed();
}

ログ ファイルを確認したところ、リクエスト ハンドラとアスペクトの両方が呼び出されていることを確認する次のログ エントリが表示されます。

    getRecordInfo(): received request
    .   .   .
    .   .   .
    validateRequest(): Entered, Thread Id: 792
    .   .   .
    .   .   .
    validateRequest(): Invalid token. The HTTP request is rejected in lack of a valid token.

メッセージにもかかわらず、クライアントには 200 が表示され、サーバー ログには他の CXF ベースのインターセプターが実行されている証拠が示されます。

ポイントカットを定義しているSpringコンテキストXMLは次のとおりです-

<bean id="vGateKeeper" class="com....core.RequestValidator" />


<aop:config>
    <aop:aspect id="methodInvocation" ref="methodInvocationProfiler">
        <aop:around method="profileMethodInvocation"
                    pointcut="execution(* org.springframework.orm.jpa.JpaTransactionManager.commit(..))"/>
        <aop:around method="profileMethodInvocation"
                    pointcut="execution(* org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(..))"/>
    </aop:aspect>
    <aop:aspect id="gateKeeper" ref="vGateKeeper">
        <aop:pointcut expression="execution(* getRecordInfo(..)) and args(httpRequest) and @annotation(modPerms)" id="my"/>
        <aop:around pointcut-ref="my" method="validateRequest"/>
    </aop:aspect>
</aop:config>

この場合、Spring AOP アスペクトを使用して HTTP 400 を返し、他のインターセプターの実行をキャンセルするにはどうすればよいですか?

また、Apache CXF インターセプターを作成して呼び出しをキャッチし、リクエスト ハンドラーに到達する前に 400 を返すことも検討していましたが、よくわかりません。リクエストハンドラの装飾。CXFインターセプターは、最終的にどのリクエストハンドラーが実行されるかを知る方法を提供していますか?

ここ ( https://cxf.apache.org/docs/interceptors.html ) を見ていましたが、とにかく見つかりませんでした。

どんな助けでも大歓迎です。

よろしく、

(*Vipul)() ;

4

1 に答える 1

2

実際、アドバイスが機能しない理由をコミュニティに尋ねても、実際のアドバイス コードを投稿しないのはかなり面白いことです。したがって、ここで行うことは当て推量だけです。次の 2 つのことが考えられます。

  • あなたのアドバイスは を返しますintが、元のコードは を返しますString。実際には、@Aroundアドバイスはラップ/インターセプトされたメソッド (または ) と同じ型を返す必要がありObjectます。
  • あなたのアドバイスは を呼び出しproceed()ますが、元のメソッドを実行したくないので、 を呼び出すべきではありませんがproceed()、独自の結果を返します。

いずれにせよ、私の2つの推測が間違っている場合は、質問を更新してください。回答を更新するか、CXFの知識を持つ他の誰か(私は知識がなく、むしろAOPの専門家です)がそれを行う方法を見つけることができますAOPなし。

PS: もう 1 つの質問: アドバイスが実際に実行されるかどうか、たとえばアドバイス内にログ メッセージを書き込むことによってテストしましたか?

于 2014-05-06T09:04:36.933 に答える