春のリダイレクトガイド

Springリダイレクトのガイド

1. 概要

この記事では、implementing a Redirect in Springに焦点を当て、各戦略の背後にある理由について説明します。

参考文献:

Spring Securityでログイン後に別のページにリダイレクトする

Spring Securityでログイン後に別のページにリダイレクトする方法の例。

Spring Security –ログイン後に以前のURLにリダイレクトする

Spring Securityでのログイン後のリダイレクトの簡単な例

Spring Securityでセッションを制御する

Spring Securityでセッションを構成する-同時セッションを設定し、セッション固定保護を有効にして、URLにセッション情報が含まれないようにします。

2. なぜリダイレクトするのですか?

まず、Springアプリケーションのthe reasons why you may need to do a redirectについて考えてみましょう。

もちろん、多くの可能な例と理由があります。 1つの簡単な方法は、フォームデータのPOST、二重送信の問題の回避、または単に実行フローを別のコントローラーメソッドに委任することです。

ここでの簡単な注意点は、通常の投稿/リダイレクト/取得パターンでは二重送信の問題に適切に対処できないことです。最初の送信が完了する前にページを更新するなどの問題でも、二重送信が発生する可能性があります。

3. RedirectViewでリダイレクトする

この単純なアプローチから始めましょう–そしてgo straight to an example

@Controller
@RequestMapping("/")
public class RedirectController {

    @GetMapping("/redirectWithRedirectView")
    public RedirectView redirectWithUsingRedirectView(
      RedirectAttributes attributes) {
        attributes.addFlashAttribute("flashAttribute", "redirectWithRedirectView");
        attributes.addAttribute("attribute", "redirectWithRedirectView");
        return new RedirectView("redirectedUrl");
    }
}

舞台裏では、RedirectViewHttpServletResponse.sendRedirect()をトリガーし、実際のリダイレクトを実行します。

ここで、we’re injecting the redirect attributes into the method –フレームワークがここで手間のかかる作業を行い、これらの属性と対話できるようにする方法に注目してください。

HTTPクエリパラメータとして公開されるモデル属性attribute –を追加します。 モデルにはオブジェクトのみが含まれている必要があります。通常は、文字列または文字列に変換できるオブジェクトです。

簡単なcurlコマンドを使用して、リダイレクトをテストしてみましょう。

curl -i http://localhost:8080/spring-rest/redirectWithRedirectView

結果は次のようになります。

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location:
  http://localhost:8080/spring-rest/redirectedUrl?attribute=redirectWithRedirectView

4. プレフィックスredirect:でリダイレクトする

以前のアプローチ–RedirectView –の使用は、いくつかの理由で最適ではありません。

まず、コードでRedirectViewを直接使用しているため、SpringAPIに結合されています。

第二に、コントローラ操作を実装するとき、結果が常にリダイレクトになることを最初から知る必要があります。これは常にそうであるとは限りません。

より適切なオプションは、プレフィックスredirect:を使用することです。リダイレクトビュー名は、他の論理ビュー名と同様にコントローラーに挿入されます。 The controller is not even aware that redirection is happening

これは次のようになります。

@Controller
@RequestMapping("/")
public class RedirectController {

    @GetMapping("/redirectWithRedirectPrefix")
    public ModelAndView redirectWithUsingRedirectPrefix(ModelMap model) {
        model.addAttribute("attribute", "redirectWithRedirectPrefix");
        return new ModelAndView("redirect:/redirectedUrl", model);
    }
}

ビュー名がプレフィックスredirect:で返されると、UrlBasedViewResolver(およびそのすべてのサブクラス)は、リダイレクトが発生する必要があることを示す特別な指標としてこれを認識します。 ビュー名の残りはリダイレクトURLとして使用されます。

ここでの簡単ですが重要な注意点は、ここでこの論理ビュー名を使用する場合、redirect:/redirectedUrlはリダイレクトrelative to the current Servlet contextを実行しているということです。

絶対URLにリダイレクトする必要がある場合は、a redirect: http://localhost:8080/spring-redirect-and-forward/redirectedUrlなどの名前を使用できます。

したがって、curlコマンドを実行すると次のようになります。

curl -i http://localhost:8080/spring-rest/redirectWithRedirectPrefix

すぐにリダイレクトされます:

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location:
  http://localhost:8080/spring-rest/redirectedUrl?attribute=redirectWithRedirectPrefix

5. プレフィックスforward:で転送

次に、少し異なることを行う方法を見てみましょう。

コードの前に、a quick, high-level overview of the semantics of forward vs. redirectについて見ていきましょう。

  • redirectは、302とLocationヘッダーの新しいURLで応答します。その後、ブラウザ/クライアントは新しいURLに対して別のリクエストを行います

  • forwardは完全にサーバー側で発生します。サーブレットコンテナは同じリクエストをターゲットURLに転送します。ブラウザでURLが変更されることはありません

それでは、コードを見てみましょう。

@Controller
@RequestMapping("/")
public class RedirectController {

    @GetMapping("/forwardWithForwardPrefix")
    public ModelAndView redirectWithUsingForwardPrefix(ModelMap model) {
        model.addAttribute("attribute", "forwardWithForwardPrefix");
        return new ModelAndView("forward:/redirectedUrl", model);
    }
}

redirect:と同じように、forward:プレフィックスはUrlBasedViewResolverとそのサブクラスによって解決されます。 内部的には、これによりInternalResourceViewが作成され、新しいビューに対してRequestDispatcher.forward()が実行されます。

curl:でコマンドを実行すると

curl -I http://localhost:8080/spring-rest/forwardWithForwardPrefix

HTTP 405(メソッドは許可されません)を取得します:

HTTP/1.1 405 Method Not Allowed
Server: Apache-Coyote/1.1
Allow: GET
Content-Type: text/html;charset=utf-8

まとめると、リダイレクトソリューションの場合の2つのリクエストと比較すると、この場合、ブラウザー/クライアントからサーバー側に送信されるリクエストは1つだけです。 もちろん、リダイレクトによって以前に追加された属性も同様に欠落しています。

6. RedirectAttributesの属性

次に–passing attributes in a redirectを詳しく見てみましょう–RedirectAttriburesでフレームワークを最大限に活用します。

@GetMapping("/redirectWithRedirectAttributes")
public RedirectView redirectWithRedirectAttributes(RedirectAttributes attributes) {

    attributes.addFlashAttribute("flashAttribute", "redirectWithRedirectAttributes");
    attributes.addAttribute("attribute", "redirectWithRedirectAttributes");
    return new RedirectView("redirectedUrl");
}

前に見たように、属性オブジェクトをメソッドに直接注入できます。これにより、このメカニズムが非常に使いやすくなります。

we are adding a flash attribute as well –これはURLに含まれない属性であることにも注意してください。 この種の属性で達成できることは、後で@ModelAttribute(“flashAttribute”)only in the method that is the final target of the redirectを使用してフラッシュ属性にアクセスできることです。

@GetMapping("/redirectedUrl")
public ModelAndView redirection(
  ModelMap model,
  @ModelAttribute("flashAttribute") Object flashAttribute) {

     model.addAttribute("redirectionAttribute", flashAttribute);
     return new ModelAndView("redirection", model);
 }

まとめると、curlで機能をテストする場合:

curl -i http://localhost:8080/spring-rest/redirectWithRedirectAttributes

新しい場所にリダイレクトされます。

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=4B70D8FADA2FD6C22E73312C2B57E381; Path=/spring-rest/; HttpOnly
Location: http://localhost:8080/spring-rest/redirectedUrl;
  jsessionid=4B70D8FADA2FD6C22E73312C2B57E381?attribute=redirectWithRedirectAttributes

このように、ModelMapの代わりにRedirectAttriburesを使用すると、リダイレクト操作に関係するsome attributes between the two methodsのみを共有することができます。

7. プレフィックスのない代替構成

次に、別の構成、つまりプレフィックスを使用しないリダイレクトについて見ていきましょう。

これを実現するには、org.springframework.web.servlet.view.XmlViewResolver:を使用する必要があります


    
        /WEB-INF/spring-views.xml
    
    

以前の構成で使用したorg.springframework.web.servlet.view.InternalResourceViewResolverの代わりに:


また、構成でRedirectViewBeanを定義する必要があります。


    

これでtrigger the redirect by referencing this new bean by idができます:

@Controller
@RequestMapping("/")
public class RedirectController {

    @GetMapping("/redirectWithXMLConfig")
    public ModelAndView redirectWithUsingXMLConfig(ModelMap model) {
        model.addAttribute("attribute", "redirectWithXMLConfig");
        return new ModelAndView("RedirectedUrl", model);
    }
}

そして、それをテストするために、再びcurlコマンドを使用します。

curl -i http://localhost:8080/spring-rest/redirectWithRedirectView

結果は次のようになります。

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location:
  http://localhost:8080/spring-rest/redirectedUrl?attribute=redirectWithRedirectView

8. HTTPPOSTリクエストのリダイレクト

銀行支払いなどのユースケースでは、HTTP POSTリクエストをリダイレクトする必要がある場合があります。 返されたHTTPステータスコードに応じて、POST要求をHTTP GETまたはPOSTにリダイレクトできます。

HTTP 1.1プロトコルreferenceに従って、ステータスコード301(永続的に移動)および302(検出)により、要求メソッドをPOSTからGETに変更できます。 この仕様では、対応する307(一時的なリダイレクト)と308(永続的なリダイレクト)のステータスコードも定義されており、リクエストメソッドをPOSTからGETに変更することはできません。

次に、投稿リクエストを別の投稿リクエストにリダイレクトするためのコードを見てみましょう。

@PostMapping("/redirectPostToPost")
public ModelAndView redirectPostToPost(HttpServletRequest request) {
    request.setAttribute(
      View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.TEMPORARY_REDIRECT);
    return new ModelAndView("redirect:/redirectedPostToPost");
}
@PostMapping("/redirectedPostToPost")
public ModelAndView redirectedPostToPost() {
    return new ModelAndView("redirection");
}

Now, let’s test the redirect of POST using the curl command

curl -L --verbose -X POST http://localhost:8080/spring-rest/redirectPostToPost

目的の場所にリダイレクトされます。

> POST /redirectedPostToPost HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.0
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 08 Aug 2017 07:33:00 GMT

{"id":1,"content":"redirect completed"}

9. 結論

この記事では、three different approaches to implementing a redirect in Spring、これらのリダイレクトを実行するときに属性を処理/渡す方法、およびHTTPPOSTリクエストのリダイレクトを処理する方法について説明しました。