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=" 100%"> <el-button type="primary" style=" 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