0

Facebook Messenger platformを使用してチャットボットアプリケーションを開発しました。 ウェブプラットフォームに埋め込まれたTomcatでSpring Bootを使用しました。 アプリケーションは、Amazon aws上で動作し、WWWにオープンし、https上のMessengerからのコールバックを受信するためのWebhookとして使用する必要があります。Amazonでスプリングブートアプリケーションを導入するためのベストプラクティス

私は、アプリケーションを安全にする方法をアドバイスする必要があるため、ハッキングされたり、Facebookから来ていないリクエストにあふれたりすることはありません。

私はアプリケーションにセキュリティで保護された(SSL)接続が必要だと思っていましたが、application.propertiesの "security.require_ssl = true"を使用しても問題はありませんでした。おそらく、私はこのことの意味とそれをどのように構成するのかが分かりません。 https要求ではない要求をブロックする方法がありますか?または、アプリケーションレベルでMessengerの外部にあるリクエストをブロックする方法はありますか?

ありがとうございました!一方

EDITは、私はハンドラインターセプターを使用してアプリケーション層で他のIPアドレスからの要求をブロック:

@Configuration 
public class MyWebApplicationInitializer implements WebApplicationInitializer, WebMvcConfigurer{ 


    @Override 
    public void addInterceptors(InterceptorRegistry registry) { 
     registry.addInterceptor(new HandlerInterceptor() { 

      @Override 
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
        throws Exception { 
       if (! (request.getRemoteAddr().equals("173.252.88.66") || request.getRemoteAddr().equals("127.0.0.1")|| request.getRemoteAddr().equals("0:0:0:0:0:0:0:1"))){ 
        logger.warn("Request is not coming from authorized remote address: " + request.getRemoteAddr()+". Rejecting"); 
        response.getWriter().write("Unauthorized Address"); 
        response.setStatus(401); 
        return false; 
       } else { 
        return true; 
       } 
      } 

} 
+0

Facebookのリファレンスドキュメントから、私は、コールバック・トークンを設定する可能性がある参照(HTTPS:/ /developers.facebook.com/docs/messenger-platform/webhook-reference)、あなたはそれを設定しましたか?あなたは春のアプリケーション側でそれを受け取りますか(パスまたはパラメータを取得する)? –

+0

@GuyBoualletトークンは初回検証用です。進行中のコールバックにはトークンが含まれていません。あなたは私が逃した何かを見ましたか? –

+1

X-Hub-Signatureと呼ばれるHTTPヘッダーがあるかどうかを確認しましたか? –

答えて

1

Facebookから送信されたリクエストで利用可能なX-Hub-signature HTTPヘッダーをwebhook URLにチェックする必要があります。

あなたの場合、署名の検証にフィルタまたはインターセプタを定義することができます。春のソーシャルプロジェクトのRealTimeUpdateController.javaにあるこの例のように、あなたのコントローラーでそれを行うこともできます。

private boolean verifySignature(String payload, String signature) throws Exception { 

     if (!signature.startsWith("sha1=")) { 

      return false; 

     } 

     String expected = signature.substring(5);  

     Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM); 

     SecretKeySpec signingKey = new SecretKeySpec(applicationSecret.getBytes(), HMAC_SHA1_ALGORITHM); 

     mac.init(signingKey); 

     byte[] rawHmac = mac.doFinal(payload.getBytes()); 

     String actual = new String(Hex.encode(rawHmac)); 

     return expected.equals(actual); 

    } 
1

ので、私はいくつかのポイントを欠場すると確信していると言うことがたくさん。

  • SSLを設定することが最初の良いことですが、証明書を取得することを確認してください。 lets encryptは、SSL証明書の支払いをしたくないと良いことです。

    だけseeing AWSは、あなたが、外部と内部の流れを開いているポートを制御できるようにするには、ファイアウォールのようなものとして、セキュリティグループを見ることができます

  • Security Groupをletsencryptする代替手段を提供します。あなたのパスワードを変更しますし、どのように

  • 明らかAWSアカウントへのアクセスを得ることができますを制御IAM

  • ルック。あなたは、インスタンス上

を作ることができ、インストールのデフォルトのパスワードは、あなたがそれを要求してハッキングや浸水されることはありません

を何ができるかについての詳細な情報を取得するためにhttps://aws.amazon.com/security/security-resources/のいくつかを読んで聞かせていない

言って申し訳ありませんが、おそらくそれはなります

- それはスキャナーを実行し、IPアドレスをスキャンし、開いているポート/ブルートフォースのログインなどをチェックするために、高度なハッカーである必要はありません...

+0

をご覧ください。あなたの答えは面白いアドバイスを提供しますが、AWSサーバー側の保護に重点を置いています。質問には、特定のクライアントが関わっています。したがって、通信のセキュリティを確保するには、どのFacebookのサポート(SSL +ペイロード署名)を確認する必要があります。 –

1

Guy Boualletのおかげで署名チェックが追加されました。 少し複雑に思えるHow to read data twice in springの問題を避けるために、私のコントローラに、インターセプタではなく、それを追加しました。

@RequestMapping(path = "/") 
public void doHandleCallback(@RequestBody String body, @RequestHeader(value = "X-Hub-Signature") String signature) throws IOException { 
    if (!verifyRequestSignature(body.getBytes(), signature)){ 
     logger.error ("Signature mismatch."); 
     throw new MismatchSignatureException(signature); 
    } 
    MessengerCallback callback = mapper.readValue(body, MessengerCallback.class); 
    logger.info("Incoming Callback: " + body); 
    for (EventData entry : callback.getEntry()) { 
     for (ReceivedMessagingObject message : entry.getMessaging()) { 
      if (message.isMessage() || message.isPostback()) { 
       doHandleMessage(message); 
      } 
      else if (message.isDelivery()){ 
       doHandleDelivery(message); 
      } 
     } 
    }  
} 

private boolean verifyRequestSignature(byte[] payload, String signature) { 
    if (!signature.startsWith("sha1=")) 
     return false; 
    String expected = signature.substring(5); 
    System.out.println("Expected signature: " + expected); //for debugging purposes 

    String hashResult = HmacUtils.hmacSha1Hex(APP_SECRET.getBytes(), payload); 
    System.out.println("Calculated signature: " + hashResult); 
    if (hashResult.equals(expected)) { 
     return true; 
    } else { 
     return false; 
    } 

} 

そして、これは例外処理クラスです::だからここ

はそれがある

@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Request Signature mismatch") 
    public class MismatchSignatureException extends RuntimeException { 
    private String signature; 

    public MismatchSignatureException(String signature) { 
     this.signature = signature; 
    } 
    @Override 
    public String getMessage() { 
     return "Signature mismatch: " + signature; 
    } 
+0

共有ありがとう! –

関連する問題