JavaによるCORSドメイン間要求の実現方法


問題
前後の分離モードを使ってプロジェクトを開発する時、よくこのような問題が発生します。
これはブラウザのソースストラテジストによるもので、安全のためです。前後の端分離開発モードが注目されている今日、フロントエンドとバックグラウンドプロジェクトは異なる環境で開発されがちです。この時、ドメインをまたいでデータを要求する需要があります。現在の解決策は主に以下の種類があります。
JSONP、iframe、プロキシモード、CORSなど
前のいくつかの方法はここでは言いません。インターネットには多くの資料があります。ここでCORSのこのような解決方法を共有します。CORSは「ドメインをまたぐ資源の共有」です。ブラウザがソースサーバにまたがり、XMLttpRequest要求を発行することができます。これによってAJAXは同じソースでしか使用できない制限を克服しました。
CORSを使ってドメインをまたがる時と普通のajax過程は同じで、ただブラウザーはこれがドメインをまたぐ要求だと発見した時に自動的にいくつかの事を処理してくれます。だから、サービス端末がサポートを提供する限り、先端は余分なことをする必要がないと言います。
実現する
実現される大まかな考えは、まずフィルタを使用して、要求対象のrequestの情報を取得することである。例えば、Originフィールド(要求がどのソースから来たかを示すか、プロトコル、ドメイン名、ポートを含む)は、事前に設定されたパラメータによって要求が正当であるかを判断し、応答対象のreponseのヘッダ情報を設定し、ドメイン間のリソース要求を実現する。インプリメンテーションを紹介する前に、私たちは先に応答ヘッダの情報を調べてみます。
応答ヘッダ
Access-Coontrol-Alllow-Mottehods
ブラウザのCORS要求を一覧表示するために使用可能なHTTP方法、例えば、GET、POST、PUT、DELETE、OPTOPS
Access-Coontrol-Alllow-Chredentials
クロスドメインCookieがサポートされているかどうかを示す。
Access-Coontrol-Allow-Headers
コンマ区切りの文字列は、サーバがサポートしているすべてのヘッダ情報フィールドを表します。
Access-Coontrol-Expose-Headers
「Access-Coontrol-Alllow-Headers」とは逆に、サポートされていないヘッダ情報フィールドを表します。
Access-Coontrol-Allow-Origin
ドメインをまたぐ要求ソース情報を許可します。プロトコル、ドメイン名、ポートを含みます。*のためにすべての要求ソースを許可します。そして一つの要求ソースしか設定できません。
Javaバックグラウンドがどうやってこの方式を実現するかを紹介します。
コード
最近はspring-bootを使っていますので、これからはspring-bootをベースに実現します。
まずCorsFilterフィルタを作成します。コードは以下の通りです。

...
@WebFilter(filterName = "corsFilter", urlPatterns = "/*",
    initParams = {@WebInitParam(name = "allowOrigin", value = "*"),
        @WebInitParam(name = "allowMethods", value = "GET,POST,PUT,DELETE,OPTIONS"),
        @WebInitParam(name = "allowCredentials", value = "true"),
        @WebInitParam(name = "allowHeaders", value = "Content-Type,X-Token")})
public class CorsFilter implements Filter {

  private String allowOrigin;
  private String allowMethods;
  private String allowCredentials;
  private String allowHeaders;
  private String exposeHeaders;

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    allowOrigin = filterConfig.getInitParameter("allowOrigin");
    allowMethods = filterConfig.getInitParameter("allowMethods");
    allowCredentials = filterConfig.getInitParameter("allowCredentials");
    allowHeaders = filterConfig.getInitParameter("allowHeaders");
    exposeHeaders = filterConfig.getInitParameter("exposeHeaders");
  }

  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    HttpServletResponse response = (HttpServletResponse) servletResponse;
    if (!StringUtils.isEmpty(allowOrigin)) {
      if(allowOrigin.equals("*")){
        response.setHeader("Access-Control-Allow-Origin", allowOrigin);
      }else{
        List<String> allowOriginList = Arrays.asList(allowOrigin.split(","));
        if (allowOriginList != null && allowOriginList.size() > 0) {
          String currentOrigin = request.getHeader("Origin");
          if (allowOriginList.contains(currentOrigin)) {
            response.setHeader("Access-Control-Allow-Origin", currentOrigin);
          }
        }
      }
    }
    if (!StringUtils.isEmpty(allowMethods)) {
      response.setHeader("Access-Control-Allow-Methods", allowMethods);
    }
    if (!StringUtils.isEmpty(allowCredentials)) {
      response.setHeader("Access-Control-Allow-Credentials", allowCredentials);
    }
    if (!StringUtils.isEmpty(allowHeaders)) {
      response.setHeader("Access-Control-Allow-Headers", allowHeaders);
    }
    if (!StringUtils.isEmpty(exposeHeaders)) {
      response.setHeader("Access-Control-Expose-Headers", exposeHeaders);
    }
    filterChain.doFilter(servletRequest, servletResponse);
  }

  @Override
  public void destroy() {

  }
}
大きな成功を収めました。今はフロントエンドでドメインをまたいでバックグラウンドのデータを取得できます。他の方法よりずっと簡単です。コードは説明しません。分かりやすくて、他のバックグラウンドの開発方式を使っても同じです。最終目的は判断要求です。応答ヘッドを設定して、フロントエンドは何もしなくてもいいです。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。