1. 程式人生 > 實用技巧 >(十)登入攔截器之前後端

(十)登入攔截器之前後端

springboot的攔截器配置:

需要在登入的方法中新增一條語句,其實只是添加了一條語句session.setAttribute("user", user);

新建 package 名為interceptor,新建類LoginInterceptor

Interceptor 即攔截器,在 Springboot 我們可以直接繼承攔截器的介面,然後實現preHandle方法。preHandle方法裡的程式碼會在訪問需要攔截的頁面時執行。

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; } }

其實就是判斷session中是否存在user屬性,如果存在就放行,如果不存在就跳轉到login頁面。

寫完了攔截器,但是它卻並不會生效,因為我們還沒有把它配置到專案中。

@SpringBootConfiguration
public class MyWebConfigurer implements WebMvcConfigurer {
    @Bean
    public LoginInterceptor getLoginIntercepter() {
        return new LoginInterceptor();
    }

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

這裡有一句非常重要的語句,即

        registry.addInterceptor(getLoginIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html");

這條語句的作用是對所有路徑應用攔截器,除了/index.html

之前我們在攔截器 LoginInterceptor 中配置的路徑,即index,觸發的時機是在攔截器生效之後。也就是說,我們訪問一個 URL,會首先通過 Configurer 判斷是否需要攔截,如果需要,才會觸發攔截器 LoginInterceptor,根據我們自定義的規則進行再次判斷。

/index/index.html是不同的,也就是說/index會觸發攔截器而/index.html不會,但根據攔截器 LoginInterceptor 中我們定義的判斷條件,以/index開頭的路徑都會被轉發,包括index.html

引入 Vuex

在我們的專案資料夾中,執行npm install vuex --save,之後,在 src 目錄下新建一個資料夾 store,並在該目錄下新建 index.js 檔案,在該檔案中引入 vue 和 vuex,程式碼如下:

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

Vue.use(Vuex)

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))
    }
  }
})

修改路由配置

import Vue from 'vue'
import Router from 'vue-router'
import AppIndex from '@/components/home/AppIndex'
import Login from '@/components/Login'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
    {
      path: '/index',
      name: 'AppIndex',
      component: AppIndex,
      meta: {
        requireAuth: true
      }
    }
  ]
})

完整的 main.js 程式碼如下:

import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
import router from './router'
import store from './store'
// 設定反向代理,前端請求預設傳送到 http://localhost:8443/api
var axios = require('axios')
axios.defaults.baseURL = 'http://localhost:8084/user/api'
// 全域性註冊,之後可在其他元件中通過 this.$axios 傳送資料
Vue.prototype.$axios = axios
Vue.config.productionTip = false
Vue.use(ElementUI)

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.message === 'success') {
            // 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/svg.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>

同時執行前後端專案,訪問 http://localhost:8080/index ,發現頁面直接跳轉到了 http://localhost:8080/login?redirect=%2Findex