(十)登入攔截器之前後端
springboot的攔截器配置:
需要在登入的方法中新增一條語句,其實只是添加了一條語句session.setAttribute("user", user);
新建 package 名為interceptor
,新建類LoginInterceptor
。
Interceptor 即攔截器,在 Springboot 我們可以直接繼承攔截器的介面,然後實現preHandle
方法。preHandle
方法裡的程式碼會在訪問需要攔截的頁面時執行。
public class LoginInterceptor implements HandlerInterceptor { @Overridepublic 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