springboot + vue の組み合わせ、バックエンド学習フロントエンド (3) (フロントエンド インターセプター + バックエンド インターセプター) はログインせずに他のページにアクセスし、ログイン インターフェイスに直接アクセスします。

ここに画像の説明を挿入

# の問題に対処する

ここに画像の説明を挿入
URL の # 番号の後のアドレスをハッシュと呼びます。この実装方法をハッシュ モードと呼びます。これは非常に典型的なフロントエンド ルーティング方法です。もう 1 つの一般的な方法は
ヒストリー モードと呼ばれます。

履歴モードを使用する

新しく追加されたコンテンツは青で表示されます
ここに画像の説明を挿入

フロントエンドをバックエンド プロジェクトにデプロイします (Tomcat のバージョンを 8.5.23 から 9.0.56 に増やす必要があります)

()
青色の [ビルド] をクリックしてパッケージ化を完了します。成功ステータスは次のようになります。または、
ここに画像の説明を挿入
コマンド npm run build による
コンテンツの場所は次のようになります
ここに画像の説明を挿入
。フロント エンドとバック エンドをマージしたい場合は、すべてのコンテンツを配置できます。 dist 内のバックエンドプロジェクトの wj\ 内 src\main\resources\static フォルダーの下

デフォルトのエラーページ

新しいページを作成する

import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

@Component
public class ErrorConfig implements ErrorPageRegistrar {
    
    

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
    
    
        ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/index.html");
        registry.addErrorPages(error404Page);
    }

}

バックエンドログインインターセプター

単純なインターセプターのロジックは次のとおりです。

1. ユーザーが URL にアクセスした場合、それがログイン ページかどうかを確認し、ログイン ページである場合は傍受しない
2. ユーザーが非ログイン ページにアクセスした場合は、ユーザーがログインしているかどうかを確認するそうでない場合は、ログインページに移動してください

LoginController がセッションを追加する

ここに画像の説明を挿入

ログインインターセプター

セッションにユーザー属性があるかどうかを確認し、存在する場合は解放され、存在しない場合はログイン ページにジャンプします。

package com.myli.base;


import com.myli.entity.User;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginInterceptor  implements HandlerInterceptor{
    
    

    @Override
    public boolean preHandle (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
    
    
        HttpSession session = httpServletRequest.getSession();
        String contextPath=session.getServletContext().getContextPath();
        String[] requireAuthPages = new String[]{
    
    
                "index",
        };
        String uri = httpServletRequest.getRequestURI();

        uri = StringUtils.remove(uri, contextPath+"/");
        String page = uri;

        if(begingWith(page, requireAuthPages)){
    
    
            User user = (User) session.getAttribute("user");
            if(user==null) {
    
    
                httpServletResponse.sendRedirect("login");
                return false;
            }
        }
        return true;
    }
    private boolean begingWith(String page, String[] requiredAuthPages) {
    
    
        boolean result = false;
        for (String requiredAuthPage : requiredAuthPages) {
    
    
            if(StringUtils.startsWith(page, requiredAuthPage)) {
    
    
                result = true;
                break;
            }
        }
        return result;
    }
}

インターセプターはプロジェクト内で構成されます

package com.myli.base.config;

import com.myli.base.LoginInterceptor;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.*;

/**
 * @author Myli
 * @create 2023-02-22 17:29
 */
@SpringBootConfiguration
public class MyMvcConfig implements WebMvcConfigurer {
    
    

    @Bean
    public LoginInterceptor getLoginIntercepter() {
    
    
        return new LoginInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry){
    
    
        registry.addInterceptor(getLoginIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html");
    }
}

URL にアクセスすると、まず Configuler を通じてインターセプトする必要があるかどうかを判断し、必要に応じてインターセプター LoginInterceptor をトリガーし、カスタム ルールに従って判断します。

/index は /index.html とは異なり、/index はインターセプターをトリガーしますが、/index.html はインターセプターをトリガーしませんが、インターセプター LoginInterceptor で定義した判定条件に従って、/index で始まるパスは次のようになります。転送され、index.html が含まれます。

ここで実行しているのは単一ページのアプリケーションであるため、事前に ErrorPage を設定しておくことで、実際にはすべてのアクセス パスが /index.html にリダイレクトされます。ブラウザのアドレスバーに /index を直接入力してインターセプターをトリガーし、インターセプターを介して /login にリダイレクトします。その後、コンフィギュラーによって /login が判断され、インターセプトが必要なパスにないため、再度インターセプターがトリガーされます。リリースされると、ページは /index.html にリダイレクトされます。コンフィギュラーで /index.html のインターセプトがキャンセルされていない場合、インターセプターが再度トリガーされ、再び /login にリダイレクトされます。

Vuex とフロントエンドのログイン インターセプター

Vuex、フロントエンドでユーザーのログイン状態を判断

Vuexをダウンロード

npm install vuex --save
ここに画像の説明を挿入

Vuex の紹介

src ディレクトリに新しいフォルダー ストアを作成し、このディレクトリに新しい Index.js ファイルを作成します。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

そのindex.jsで続行します

export default new Vuex.Store({
    
    
  state: {
    
    
    user: {
    
    
      username: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).username
    }
  },
  mutations: {
    
    
    login (state, user) {
    
    
      state.user = user
      window.localStorage.setItem('user', JSON.stringify(user))
    }
  }
})

state は状態を意味し、ユーザー情報
の変更を記録するメソッドです。このメソッドがトリガーされると、ユーザー オブジェクトに値を割り当てることができます。

localStorage: ローカルストレージプロジェクトを開いたときにローカルストレージにユーザーオブジェクトがあるかどうかを判断し、存在する場合は取り出してユーザー名の値を取得し、存在しない場合はユーザー名を設定します空。このように、キャッシュをクリアしない限り、ログイン状態は常に保存されます。
ここに画像の説明を挿入

ルーティング構成を変更する

src\router\index.js は
requireAuth フィールドを設定します

    {
    
    
     path: '/index',
     name: 'AppIndex',
     component: AppIndex,
     meta: {
    
    
       requireAuth: true
     }
   }

ここに画像の説明を挿入

フック関数

beforeEach() はフロントエンドインターセプトの中核です
ここに画像の説明を挿入

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import store from './store'

// 设置反向代理,前端请求默认发送到 http://localhost:8443/api
var axios = require('axios')
axios.defaults.baseURL = 'http://localhost:8443/api'

// 全局注册,之后可在其他组件中通过 this.$axios 发送数据
Vue.prototype.$axios = axios

Vue.config.productionTip = false

Vue.use(ElementUI)

// 钩子函数
// beforeEach() 函数判断访问的路径是否需要登录,
// router.beforeEach(),意思是在访问每一个路由前调用。
// 如果需要,判断 store 里有没有存储 user 的信息,
// 如果存在,则放行,否则跳转到登录页面,并存储访问的页面路径(以便在登录后跳转到访问页)。
router.beforeEach((to, from, next) => {
    
    
  if (to.meta.requireAuth) {
    
    
    if (store.state.user.username) {
    
    
      next()
    } else {
    
    
      next({
    
    
        path: 'login',
        query: {
    
    redirect: to.fullPath}
      })
    }
  } else {
    
    
    next()
  }
}
)
/* eslint-disable no-new */
new Vue({
    
    
  el: '#app',
  render: h => h(App),
  router,
  store,
  components: {
    
     App },
  template: '<App/>'
}
)

login.vue

渡されたユーザー情報を保存する

<template>
  <body id="poster">
    <el-form class="login-container" label-position="left"
             label-width="0px">
      <h3 class="login_title">系统登录</h3>
      <el-form-item>
        <el-input type="text" v-model="loginForm.username"
                  auto-complete="off" placeholder="账号"></el-input>
      </el-form-item>
      <el-form-item>
        <el-input type="password" v-model="loginForm.password"
                  auto-complete="off" placeholder="密码"></el-input>
      </el-form-item>
      <el-form-item style="width: 100%">
        <el-button type="primary" style="width: 100%;background: #505458;border: none" v-on:click="login">登录</el-button>
      </el-form-item>
    </el-form>
  </body>
</template>

<script>

  export default {
    
    
    name: 'Login',
    data () {
    
    
      return {
    
    
        loginForm: {
    
    
          username: 'admin',
          password: '123'
        },
        responseResult: []
      }
    },
    methods: {
    
    
      login () {
    
    
        var _this = this
        console.log(this.$store.state)
        this.$axios
          .post('/login', {
    
    
            username: this.loginForm.username,
            password: this.loginForm.password
          })
          .then(successResponse => {
    
    
            if (successResponse.data.code === 200) {
    
    
              // var data = this.loginForm
              _this.$store.commit('login', _this.loginForm)
              var path = this.$route.query.redirect
              this.$router.replace({
    
    path: path === '/' || path === undefined ? '/index' : path})
            }
          })
          .catch(failResponse => {
    
    
          })
      }
    }
  }
</script>

<style>
  #poster {
    
    
    background:url("../assets/eva.jpg") no-repeat;
    background-position: center;
    height: 100%;
    width: 100%;
    background-size: cover;
    position: fixed;
  }
  body{
    
    
    margin: 0px;
  }
  .login-container {
    
    
    border-radius: 15px;
    background-clip: padding-box;
    margin: 90px auto;
    width: 350px;
    padding: 35px 35px 15px 35px;
    background: #fff;
    border: 1px solid #eaeaea;
    box-shadow: 0 0 25px #cac6c6;
  }
  .login_title {
    
    
    margin: 0px auto 40px auto;
    text-align: center;
    color: #505458;
  }
</style>


ログインテスト

アカウントのパスワードを入力してログインし
、保存されているかどうかを確認してから
ここに画像の説明を挿入
、ユーザー行のデータを直接削除し、
インデックスページに再度アクセスしてください。ログインインターフェイスに直接移動すると、成功とみなされます
。エラーが発生した場合は、まずウェブストームを再起動してから、エラーが存在するかどうかを確認し、存在する場合は解決します。

注: ストアの下の indesx.js で window.localStorage を window.sessionStorage に置き換えます。データはブラウザが閉じられなくなるまで保持されますが、永続的に存在するわけではありません。

おすすめ

転載: blog.csdn.net/m0_54765221/article/details/129210088