フロントエンドページとバックエンドページの分離によりセッションが正常に取得できない問題

       フロントエンド ページとバックエンド ページの分離によって引き起こされるクロスドメインの問題とセッション損失の解決策

新入生の皆さんは、この新しい記事を読んでください。この記事は適用されなくなりました:  新しいバージョンの Chrome ブラウザで繰り返されるジャンプ ログインの問題の分析

 数日前、経験不足のため、見つけるのに長い時間がかかった問題に遭遇しました。これは私のコンピュータの仮想マシン上に作成した Java サーバー インターフェイスです。ログインしてログイン インターフェイスを確認するときに、ユーザー データを保存するためにセッションが使用されます。HTML をプロジェクトに配置すると、セッション値が非常によく取得されます。 , しかし、htmlがフロントエンドスタッフ自身のコンピュータに配置されている場合、セッションは対応する値を取得できません。

オンラインで検索したところ、これはフロントエンド ページとバックエンド ページの分離によって引き起こされる問題であることがわかりました。多くのネチズンはすでに非常に優れた具体的な解決策を述べています。具体的なソリューションについては、クロスドメインをサポートし、セッションが失われないフロントエンドとバックエンドの分離プロジェクトを参照してください。前後に異なる場所にデプロイしてもセッションは失われない_woshiyeguiren のブログ - CSDNブログ

そこで宣伝をさせてください。初めて Java のブロックを解除してからほぼ 2 週間が経ち、会社用に PBR マテリアル ライブラリを作成しました。興味のある友達は見て、クリックしてリンクを開くことができます

2018.10.24 追加:

Java に初めて触れたときにこの落とし穴に遭遇しましたが、その後同じ問題に遭遇することになるとは、これほど時間がかかるとは予想していませんでした。

クロスドメインの問題は、Web 開発では非常に一般的です。たとえば、プロジェクトをデプロイするときに、フロントエンド コードを 1 つのサーバー (oss) に配置し、バックエンド コードを別のサーバーに配置すると、クロスドメインの問題が発生します。 2 つのドメイン間の転送や構成は必要ありません。第 2 に、インターフェイス開発を使用するため、必然的にフロントエンド コードはフロントエンド スタッフのコンピュータに配置され、バックエンド コードはバックエンド スタッフのコンピュータに配置されます。これにより、クロスドメインの問題も発生します。ただし、インターフェイス ドッキングを実行すると、フロントエンド担当者がバックエンド担当者のコンピュータに直接アクセスできるようになり、問題が両方の当事者に明確に報告されるため、この方法での直接変更は非常に迅速な開発プロセスとなるはずです。したがって、オンラインサーバーに展開するときにクロスドメインの問題が発生するかどうかは考慮されておらず、2 番目の状況によって引き起こされるクロスドメインの問題とセッション損失の問題を全員で解決する必要があります。

1:ネイティブJava記述方法のバックグラウンド処理方法

①: バックグラウンドで統一されたリクエストを返すインターフェースを作成し、ヘッダーを設定します。リクエストしたデータが返されたときに一律に呼び出されます

  // 返回json字符串数据
    void post_jsondata(HttpServletRequest request, HttpServletResponse response, JSONObject output)
            throws ServletException, IOException {
        response.setContentType("text/html");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");//是否支持跨域
        response.setHeader("Access-Control-Allow-Methods", "GET,POST");
        PrintWriter out = response.getWriter();
        out.println(output.toString());
        out.flush();
        out.close();
        // super.doPost(request, response);
    }

②: フロントエンド ページのコードでは、ajax リクエストに属性 xhrFields: {withCredentials: true} を含めます。これは、Cookie 情報を提供することを意味します。

<button id="buttom2b">用户端-测试按钮2</button>
    <script type="text/javascript">
        $("#buttom2b").click(function() {
            var shit = {
                    store_id:2
            };
            $.ajax({
                type : 'post',
                url : "http://192.168.0.15:8080/carplatform/User/test2",
                dataType : 'json',
                contentType : "application/json;charset=UTF-8",
                data : JSON.stringify(shit),
                xhrFields: {withCredentials: true},
                success : function(xxx) {
                console.log(xxx);
                }
            });
        });
    </script>

2:フレームワーク(ssm)によるJavaバックグラウンド処理方法
     

デスクトップ上に html ファイルを作成してバックエンド Java コードにアクセスし、フロント ページとリア ページの分離をシミュレートします。これにより、セッション損失の問題が発生します。

この問題に遭遇したときの修正手順は以下の通りでした。
①:何も設定せずに直接アクセスするためにajaxを使用すると、エラー 403 Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin ' ヘッダーが要求されたリソースに存在します。そのため、オリジン 'null' はアクセスを許可されません。応答には HTTP ステータス コード 403 がありました。明らかに、これはクロスドメインであり、バックエンドが要求を拒否しました。
②: バックエンド コントローラーにアノテーション「@CrossOrigin(origins = "*", maxAge = 3600)」を追加してすべてのリクエストを許可し、バックエンド メソッドにアクセスできるようにすることで、クロスドメインの問題を解決します。
③: しかし新たな問題が発生し、バックグラウンドで request.getSession() が呼び出されている限り (または springmvc のパラメータとしてセッションが直接渡されている限り)、リクエストを行うたびに新しいセッションが生成されます。
④:ネイティブJavaで書く場合、フロントエンドのajaxにxhrFields: {withCredentials: true}という属性があるので、これも追加します。1 つのテストでエラーが報告されましたが、これはおそらくクロスドメインの問題でした。うーん、クロスドメインはすでに許可されているのではないでしょうか? どういうことですか? 情報を確認すると、大まかに言うと、アノテーション「@CrossOrigin(origins = "*", maxAge = 3600)」は get リクエストにのみ適用されます。
⑤:ネイティブJavaで解決できるので、フレームワークに置き換えることは確実に可能です。情報を検索した結果、必要なのは応答のヘッダーを毎回設定することであることがわかりました。オンラインで言われているところによると、各リクエストをインターセプトして、コントローラーに入る前に設定できれば、問題は確実に解決されるそうです。

具体的な書き方: ①リクエストごとにインターセプトしてレスポンスヘッダーを設定するインターセプタークラスを新規作成します。②:このインターセプターをwebxmlに登録します。 ③:フロントエンドのajaxプラス「xhrFields: {withCredentials: true}」に注意してください

拦截器类///
package com.xunshi.TimerEvent;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author liangpeng
 * @ClassName: AuthorityInterceptor拦截器,拦截每次请求
 * @Description: 前后端分离导致session不一致问题
 * @date 2018年10月18日  
 */
public class AuthorityInterceptor implements Filter {
    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setContentType("textml;charset=UTF-8");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "0");
        response.setHeader("Access-Control-Allow-Headers",
                "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("XDomainRequestAllowed", "1");
        chain.doFilter(req, res);
    }
    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }
}
///webxml配置,添加注册///
  <!--自定义拦截器,每次请求拦截,设置session跨域以及维持session配置  -->
  <filter>
       <filter-name>AuthorityInterceptor</filter-name>
       <filter-class>com.xunshi.TimerEvent.AuthorityInterceptor</filter-class>
    </filter>
    <filter-mapping>
       <filter-name>AuthorityInterceptor</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>

3: WeChat アプレット セッションの問題のフロントエンド処理とバックエンド コードの変更

上記の 2 つは基本的な ajax リクエスト用ですが、WeChat ミニ プログラムの場合、ミニ プログラムは ajax を使用して http リクエストを行うことができないため、WeChat ミニ プログラムのクロスドメイン セッションの問題の処理は少し異なります。
具体的な方法は次のとおりです。 ① 最初のミニ プログラム アクセスの後、バックエンドはミニ プログラムのセッション ID (できれば暗号化されたもの) を返します。他に何も設定する必要はありません。②: ミニ プログラムがセッション ID を要求するたびに、Java バックグラウンドはセッション ID に基づいてどのクライアントであるかを自動的に判断し、対応するセッションを見つけます。
  

       wx.request({
            url: getApp().globalData.url + 'User/ShowOneCar/' + res.data.car_id,
            header: { "Cookie": "JSESSIONID=" + wx.getStorageSync("sessionID") },//带上这句话,sessionID是登陆后后端返回存在缓存里面的
            success: function (rr) {
              console.log(rr);
              if (rr.data.state) {
                that.setData({
                  carinfo: rr.data.thiscar
                });
              }
            }
          })

ミニプログラムのセッション問題は、バックグラウンドで設定するためのインターセプタを作成する必要がないのですが、ajaxが動かないのが少々ややこしいです。
ただし、セッションを使用してデータを保存するには、セキュリティやサーバーの負荷の問題など、多かれ少なかれ問題があります。しかし、現時点ではユーザーのログイン状態を保存するこれより簡単な方法を知らないので、まずはそれを使ってみましょう。

おすすめ

転載: blog.csdn.net/qq_22824481/article/details/81004051