単一ページアプリケーションにおけるログイン状態保持とページアクセス制御の解決策


単一ページの適用と複数ページの適用


従来のウェブプロジェクトの多くは、ページがジャンプするたびに、バックグラウンドサーバが新しいhtmlとそれに関連するcssjsリソース、例えばよく知られているJSPを返すマルチページアプリケーションである.この応用の最も明らかな欠点は,ページ切替の応答速度が遅いこと,静的リソースの繰返しロードなどである.
一方、単一ページアプリケーション(SPA)は、ページジャンプ時に、新しいhtmlcssjsなどのリソースを要求する必要がなく、多くのhttp要求を節約し、ページ切り替えの速度を速めることができる.しかし、アプリケーションを最初にロードするときにすべてのページを取得し、最初のスクリーンのロード時間が長くなるという明らかな欠点もあります.幸いなことに、サービス側レンダリング(SSR)技術はこの問題をうまく解決することができる.
総合的に見ると,中小規模の応用については,現在では前後端分離を強調する時代に,単ページ応用が好ましい.次の共有は、vuevue-routerおよびvuexを使用して、単一ページアプリケーションを開発する際に発生したいくつかの問題と対応する解決方法です.

単一ページで適用されるアクセス権


単一ページアプリケーションは、各ページに1つのhtmlファイルといくつかのcssファイルとjsファイルを新規作成する必要はありません.ページ切替にはバックエンドの制御は必要ありません.フロントエンドの開発者には友好的に見えるようですが、実際には、多くの単一ページアプリケーションでは、フロントエンドの開発者が考慮しなければならないことが多いようです.主にページアクセス権限の制御にあり、例えばハッシュモードではurlのハッシュ値を手動で変更して異なるルーティングにアクセスすることができるが、実際の応用では、ユーザのこのような操作に対して判断制御が必要であり、例えば、一部のルーティングはログイン後にアクセス権限が必要であり、一部のルーティングに対応するページは特別な権限が必要でアクセスできるなどである.
単一ページアプリケーションのページタイプを次の2つに分けます.
  • 登録ページ
  • アクセスするにはログインが必要なページ
  • ログインページの権限制御


    ログインページの特殊な点は、ログインページは、ユーザがログイン操作を行う必要がある場合にのみ表示されるべきであり、すなわち、ユーザのログイン状態が期限切れでなければ、ユーザはログインページのルーティングにアクセスできないことである.

    ログイン後にアクセスできるページの権限制御

    vueアプリケーションでは、通常、mountedメソッドでajax要求取得データが送信される.しかし、単一ページアプリケーションではurlのハッシュ値を変更して異なるルーティングにアクセスすることができるが、パーソナルセンターなどの一部のページでは、有効なデータを表示するには、ユーザーがログインしてから有効なデータを取得する必要がある.ユーザがこのルーティングのページにアクセスできるようにする簡単な処理方法があるが、ajaxは有効なデータを取得できないが、明らかに最善の解決策ではない.好ましい方法は、vue-routerのライフサイクル関数によって、これらのルーティングに入る前に、ユーザがログインしているかどうかを判断し、ログインしていない場合はログインページのルーティングにリダイレクトすることである.
    router.beforeEach((to, from, next) => {
        if (to.path == '/login') { //          
            if (login) { //       ,      
                next('/');
            } else { //     
                next();
            }
        } else { //        
            if (login) { //       ,    
                next();
            } else { //     ,        
                next('/login');
            }
        }
    })

    ログインステータス


    以上の解析により,問題は最終的にフロントエンドがユーザのログイン状態をどのように判断するかを指す.
    通常、フロントエンドは要求の送信のみを担当し、応答表示ページによって異なる内容が表示され、その後、sessionIdまたはtokenによってユーザのログイン状態が期限切れであるか否かが判断される.では、フロントエンドでは、ユーザーのログイン状態が有効かどうかを記録(保存)する方法はありますか?

    クライアントストレージ

    sessionStoragelocalStoragecookieは、フロントエンドでよく使用されるクライアント記憶方法である.

    cookie


    バックエンドに記憶能力を持たせる解決策としては、通常、sessionId/tokenのようなバックエンド判定要求が誰に来たのかを判断する情報が携帯され、前述したように、これらの情報はバックエンドによって期限切れか否かが判断され、一般的にはcookieにログイン状態が有効か否かを直接記憶することはない.

    sessionStorage


    ブラウザに格納すると、ユーザ登録に成功した後にsetItemで属性を保存し、ルーティングのライフサイクル関数beforeEachgetItemで登録済みか否かを判断することができる.実装は簡単ですが、多くの問題があります.
  • sessionStorage自体の有効期限は、ユーザのログイン状態がsessionStorageの有効期限と同期することを決定する.たとえば、バックエンドにcookieexpireプロパティが設定されているかどうかにかかわらず、ブラウザを閉じた後に再ログインする必要があります.
  • バックエンドのログイン状態が期限切れになったが、sessionStorageはまだ有効であり、ユーザーが本能的にページにアクセスできるようになったが、データがないだけだ.ユーザーは、いくつかの操作でsessionStorageを無効にすることができます(ブラウザウィンドウを閉じて再読み込み)
  • バックエンドのログインステータスは有効ですが、sessionStorageがなくなり、ユーザーが再ログインする必要があります.

  • sessionStorageは読み書き可能であり、ブラウザのデバッグツールではclearなどの方法を簡単に実行でき、setItemの値を簡単に読み取ることができ、セキュリティが低いことによってsessionStorageは重要な情報を格納できないことが決定される.

  • localStorage


    有効期限がsessionStorageと異なる場合を除き、他の機能は類似しています.

    ストレージの適用


    アプリケーションに格納されるのは、通常、vuexにユーザがログインしているかどうかを記録することである.ルーティングのライフサイクル関数beforeEachでこのデータを読み出し、ユーザのログイン状態が有効か否かを判断する.では、質問が来ました.
  • 登録に成功してからこのデータを更新しても大丈夫ですが、いつこのデータを更新する必要がありますか?更新しないでログイン有効状態
  • 直接ページをリフレッシュしてからvuexが空になりましたが、バックエンドのログイン状態が有効であれば、再ログインしますか?

  • 私の解決策は、ログインステータスが有効かどうかを判断するリクエストを送信することです.データの取得要求に対して、戻り値の情報が再ログインを必要とする場合、vuexをクリアし、ログインページにリダイレクトする.vuexを利用してログイン状態を記録する際に発生するすべての状況と処理方法を見てみましょう.
    router.beforeEach(async (to, from, next) => {
        if (to.path == '/login') { //          
            if (store.login) {
                //       ,      
                //                url    hash
                next('/');
            } else {
                //    ajax           
                const login = await ajax();
                if (login) {
                    //    store,      
                    store.commit('login', true);
                    next('/');
                } else {
                    next();    
                }
            }
        } else { //        
            if (store.login) {
                //       ,    
                next();
            } else {
                //                 ,                url    hash
                //    ajax           
                const login = await ajax();
                if (login) {
                    //    store,    
                    store.commit('login', true);
                    next();
                } else {
                    next('/login');    
                }
            }
        }
    })

    また、各取得データの要求に対して、バックエンドの戻り値においてユーザのログイン状態が期限切れである場合、vuexのログイン状態を変更してログインページにリダイレクトする.
    store.commit('login', false);
    location.href = '/#/login';
    location.reload();