前后端不分离的情况下,在后端怎么实现拦截器:
思路:
访问url,检测是不是登录界面,如果是登录界面,就不拦截,如果不是,判断是不是已经登录,如果登录不拦截,没登录拦截到登录界面
缓存用户信息:
@Controller public class LoginController { @Autowired UserService userService; @CrossOrigin @PostMapping(value = "/api/login") @ResponseBody public Result login(@RequestBody User requestUser, HttpSession session) { String username = requestUser.getUsername(); username = HtmlUtils.htmlEscape(username); User user = userService.get(username, requestUser.getPassword()); if (null == user) { return new Result(400); } else { / //主要是这句代码,当登录成功的时候将用户信息存在session里面 session.setAttribute("user", user); return new Result(200); } } }
创建拦截器:
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; } }
拦截器配置到项目:
@SpringBootConfiguration public class MyWebConfigurer implements WebMvcConfigurer { @Bean public LoginInterceptor getLoginIntercepter() { return new LoginInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry){ /表示除了index的页面,其余的页面都会拦截 registry.addInterceptor(getLoginIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html"); } }
Vuex 与前端登录拦截器:
使用vuex实现前端拦截器的实现:
项目运行npm install vuex --save安装vuex
在src文件夹下面创建store文件夹,然后创建 index.js文件,在里面引入vue和vuex
/store/index.js: 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)) } } })
配置路由:
/route/index.js: 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 } } ] })/src/main.js: import Vue from 'vue' import App from './App' import router from './router' import store from './store' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' var axios = require('axios') axios.defaults.baseURL = 'http://localhost:8443/api' 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: '' })
登陆:
思路:1.点击登录按钮,向后端发送数据
2.受到后端返回的成功代码时,触发 store 中的 login() 方法,把 loginForm 对象传递给 store 中的 user 对象
(*这里只是简单的实现,在后端我们可以通过用户名和密码查询数据库,获得 user 表的完整信息,比如用户昵称、用户级别等,返回前端,并传递给 user 对象,以实现更复杂的功能)
3.获取登录前页面的路径并跳转,如果该路径不存在,则跳转到首页
修改login里面的代码:
<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>
前后台启动之后:输入 http://localhost:8080/index
显示,成功拦截到登录界面:
页面开发:
创建父组件,由于登录的时候不可创建父组件,故创建src/home/Home.vue文件: <template> <div> <nav-menu>nav-menu> <router-view/> div> template> <script> import NavMenu from './common/NavMenu' export default { name: 'Home', components: {NavMenu}//加载导航 }script> <style scoped>style>router/index.js添加路由: import Vue from 'vue' import Router from 'vue-router' import AppIndex from '../components/home/AppIndex' import Login from '../components/Login' import Home from '../components/Home' import LibraryIndex from '../components/library/LibraryIndex' Vue.use(Router) export default new Router({ mode: 'history', routes: [ { path: '/home', name: 'Home', component: Home, // home页面并不需要被访问 redirect: '/index', children: [ { path: '/index', name: 'AppIndex', component: AppIndex, meta: { requireAuth: true } }, { path: '/library', name: 'Library', component: LibraryIndex, meta: { requireAuth: true } } ] }, { path: '/login', name: 'Login', component: Login } ] })然后创建导航: <template> <el-container> <el-aside style="width: 200px;margin-top: 20px"> <switch>switch> <SideMenu>SideMenu> el-aside> <el-main> el-main> el-container> template> <script> import SideMenu from './SideMenu' export default { name: 'AppLibrary', components: {SideMenu} }script> <style scoped>style>创建导航: <template> <el-menu class="categories" default-active="0" @select="handleSelect" active-text-color="red"> <el-menu-item index="0"> <i class="el-icon-menu">i> <span slot="title">全部span> el-menu-item> <el-menu-item index="1"> <i class="el-icon-menu">i> <span slot="title">文学span> el-menu-item> <el-menu-item index="2"> <i class="el-icon-menu">i> <span slot="title">流行span> el-menu-item> <el-menu-item index="3"> <i class="el-icon-menu">i> <span slot="title">文化span> el-menu-item> <el-menu-item index="4"> <i class="el-icon-menu">i> <span slot="title">生活span> el-menu-item> <el-menu-item index="5"> <i class="el-icon-menu">i> <span slot="title">经管span> el-menu-item> <el-menu-item index="6"> <i class="el-icon-menu">i> <span slot="title">科技span> el-menu-item> el-menu> template> <script> export default { name: 'SideMenu' }script> <style scoped> .categories { position: fixed; margin-left: 50%; left: -600px; top: 100px; width: 150px; }style>
----完