目录
1 权限系统:
2 完成登录
2.1 前端布局
2.2 完成后端登录接口
3 登录的bug
1 权限系统:
1.前端使用: vue + elementui + axios + css + html
2.后端使用: springboot+mybatis-plus +mybatis+druid+shiro+swagger2+redis
2 完成登录
2.1 前端布局
<template>
<!--这里必须使用一个双标签-->
<div id="login_box">
<div class="img_position">
<el-avatar :size="140" :src="imgUrl"></el-avatar>
</div>
<el-card class="box-card">
<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="name">
<el-input type="text" v-model="ruleForm.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="ruleForm.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary"
size="mini"
:plain="true"
style="margin-left: 100px;width: 100px">登录</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
export default {
name: "Login",
data(){
return {
ruleForm: {
name: '',
password: ''
},
rules: {
name: [
{required: true, message:'用户名不能为空', trigger: 'blur'},
{validator:function (rule, value, callback) {
axios.get("/qy151_16/emp/check?name="+value).then(function (result) {
if(result.data.code === 200){
app.imgUrl = result.data.data;
callback();
}else {
app.imgUrl = 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png';
callback(new Error("用户名不存在"));
}
})
}, trigger: 'blur'}
],
password: [
{required: true, message: '密码不能为空', trigger: 'blur'},
]
},
imgUrl:'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
}
}
}
</script>
<style>
#login_box{
position: relative;
width: 500px;
margin: 250px auto;
}
#login_box div.img_position{
position: absolute;
left: 200px;
top: -70px;
}
.text {
font-size: 14px;
}
.item {
padding: 18px 0;
}
.box-card {
padding: 100px 50px 0 0;
width: 480px;
}
</style>
(2)登录按钮事件
如果想在vue工程中使用axios进行异步请求,则需要在main.js中导入axios
[1]//导入axios
import axios from "axios";
[2]//把axios挂载到vue对象中,以后在vue中如果使用axios直接可以用$http名称
Vue.prototype.$http=axios
methods:{
login(){
//表单校验
this.$refs['ruleForm'].validate((valid) => {
if(valid){
//url:后端登录接口的路径
this.$http.post("http://localhost:8808/user/login",this.ruleForm).then(result=>{
});
}
})
}
}
2.2 完成后端登录接口
(1)依赖
?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ykq</groupId>
<artifactId>qy151-springboot-vue</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>qy151-springboot-vue</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.9.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
(2)mp的代码生成器
package com.xzj;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;
/**
* @author xuan
*/
public class Generator {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/shiro-permission?serverTimezone=Asia/Shanghai", "root", "pAssW0rd")
.globalConfig(builder -> {
builder.author("xzj") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir(".\\src\\main\\java\\"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.xzj") // 设置父包名
.moduleName("system") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.xml, "src\\main\\resources\\mapper\\")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("acl_user","acl_role","acl_permission")// 设置需要生成的表名
.addTablePrefix("acl_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
(3) 配置application文件
server.port=8808
spring.datasource.druid.url=jdbc:mysql://localhost:3306/shiro-permission?serverTimezone=Asia/Shanghai
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.username=root
spring.datasource.druid.password=root#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
(4)接口
package com.xzj.system.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xzj.system.entity.User;
import com.xzj.system.service.IUserService;
import com.xzj.vo.CommonResult;
import com.xzj.vo.LoginVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* @author xuan
*/
@RestController
@RequestMapping("/system")
@Api(tags = "登录的接口类")
public class LoginController {
@Autowired
private IUserService userService;
@PostMapping("/login")
@ApiOperation(value ="登录接口")
public CommonResult login(@RequestBody LoginVo loginVo){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username",loginVo.getUsername());
wrapper.eq("password",loginVo.getPassword());
wrapper.eq("is_deleted",0);
User user = userService.getOne(wrapper);
System.out.println(user);
if (user!=null){
return new CommonResult(2000,"登录成功",token);
}else{
return new CommonResult(5000,"登录失败",null);
}
}
}
前端调用后端登录接口时出现如下的错误
为跨域问题:
当使用异步请求从一个网址访问另一个网址时可能会出现跨域问题。
前提:
1. 必须为异步请求
2. 当端口号或协议或ip不同时则会出现跨域
出现两个请求: 有一个请求的方式为: OPTIONS 和真实的请求方式
理解: OPTIONS先头部队。---探视后台有没有解决跨域。
如何解决跨域:
后端解决---->这里也有几种方式:
【1】可以借助nginx.
【2】在代码中解决
(origins = {"192.168.0.111:8080","192.168.0.120:8081"},allowedHeaders="运行哪些请求头跨域",methods={"GET","POST"})
origins: 允许哪些域可以跨域访问我这个接口
allowedHeaders:允许哪些请求头信息跨域
methods: 允许哪些请求方式跨域
上面再控制层接口处加上注解的方式解决跨,麻烦的地方就需要对每个控制类都加该注解。 设置一个全局跨域配置类
package com.xzj.system.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* @author xuan
*/
@Configuration
public class CorsConfig {
// 当前跨域请求最大有效时长。这里默认1天
private static final long MAX_AGE = 24 * 60 * 60;
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
corsConfiguration.setMaxAge(MAX_AGE);
source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
return new CorsFilter(source);
}
}
登录成功后前端路由跳转
3 登录的bug
上面咱们写的登录,后端没有保存数据 前端也没有拿到数据进行保存
修改登录的接口
package com.xzj.system.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xzj.system.entity.User;
import com.xzj.system.service.IUserService;
import com.xzj.vo.CommonResult;
import com.xzj.vo.LoginVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* @author xuan
*/
@RestController
@RequestMapping("/system")
@Api(tags = "登录的接口类")
public class LoginController {
@Autowired
private IUserService userService;
@Autowired
private RedisTemplate redisTemplate;
@PostMapping("/login")
@ApiOperation(value ="登录接口")
public CommonResult login(@RequestBody LoginVo loginVo){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username",loginVo.getUsername());
wrapper.eq("password",loginVo.getPassword());
wrapper.eq("is_deleted",0);
User user = userService.getOne(wrapper);
System.out.println(user);
if (user!=null){
String token = UUID.randomUUID().toString();
ValueOperations forValue = redisTemplate.opsForValue();
forValue.set(token,user,24, TimeUnit.HOURS);
return new CommonResult(2000,"登录成功",token);
}else{
return new CommonResult(5000,"登录失败",null);
}
}
}
修改前端登录方法
后面每次请求都可以携带该token,
每次请求都得要人为添加参数token. 我们可以使用axios得请求拦截器
4 前置路由守卫
前置路由守卫:就是在路由跳转前加上自己得一些业务代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'
//导入axios
import axios from "axios";
Vue.config.productionTip = false
//设置axios的请求拦截器---在请求头上添加token
axios.interceptors.request.use(config=>{
var token = sessionStorage.getItem("token");
if(token){
config.headers.token=token;
}
return config;
}),
//设置前置路由守卫 to:到哪个路由 from:从哪个路由来 next():放行到指定路由
router.beforeEach(((to, from, next) => {
//获取跳转得路径
var path = to.path;
//判断是否为登录路由路径
if(path==="/login"){
//放行
return next();
}
//其他路由路径 判断是否登录过
var token = sessionStorage.getItem("token");
if(token){
return next();
}
//跳转登录
return next("/login");
})
)
// 设置axios基础路径
axios.defaults.baseURL="http://localhost:8808"
Vue.prototype.$http =axios
new Vue({
router,
render: h => h(App)
}).$mount('#app')
5 整合shiro
(1)依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.7.0</version>
</dependency>
(2) shiro得配置类
package com.xzj.system.config;
import com.xzj.system.filter.LoginFilter;
import com.xzj.system.realm.MyRealm;
import com.xzj.system.service.IUserService;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.filter.DelegatingFilterProxy;
import javax.servlet.Filter;
import java.util.HashMap;
/**
* @author xuan
*/
@Configuration
public class shiroConfig {
@Bean
public DefaultWebSecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm());
return securityManager;
}
@Bean
public Realm realm(){
MyRealm myRealm = new MyRealm();
myRealm.setCredentialsMatcher(credentialsMatcher());
return myRealm;
}
@Bean
public CredentialsMatcher credentialsMatcher (){
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5");
credentialsMatcher.setHashIterations(1024);
return credentialsMatcher;
}
@Autowired
private RedisTemplate redisTemplate;
@Bean(value = "shiroFilter")
public ShiroFilterFactoryBean filterFactoryBean(){
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager());
HashMap<String, String> map = new HashMap<>();
map.put("/system/login","anon");
map.put("/*.css","anon");
map.put("/doc.html","anon");
map.put("/v2/api-docs", "anon");
map.put("/configuration/security","anon");
map.put("/swagger-resources", "anon");
map.put("/configuration/ui", "anon");
map.put("/**","authc");
factoryBean.setFilterChainDefinitionMap(map);
HashMap<String, Filter> filterMap = new HashMap<>();
filterMap.put("authc",new LoginFilter(redisTemplate));
factoryBean.setFilters(filterMap);
return factoryBean;
}
@Bean
public FilterRegistrationBean<Filter> filterRegistrationBean(){
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setName("shiroFilter");
filterRegistrationBean.setFilter(new DelegatingFilterProxy());
return filterRegistrationBean;
}
//开始shiro注解
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
}
(3)增加一个realm类对象
package com.xzj.system.realm;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xzj.system.entity.User;
import com.xzj.system.service.IUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/**
* @author xuan
*/
public class MyRealm extends AuthorizingRealm {
@Autowired
private IUserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// User user = (User) principalCollection.getPrimaryPrincipal();
//
// List<String> list = userService.selectByUserId(user.getUserid());
// if(list!=null&&list.size()>0){
// SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// info.addStringPermissions(list);
// return info;
// }
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String) authenticationToken.getPrincipal();
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username",username);
wrapper.eq("is_deleted",0);
User user = userService.getOne(wrapper);
if(user!=null){
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,
user.getPassword(),credentialsSalt,this.getName());
return info;
}
return null;
}
}
(4) 修改controller代码
package com.xzj.system.controller;
import com.xzj.system.service.IUserService;
import com.xzj.system.vo.CommonResult;
import com.xzj.system.vo.LoginVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* @author xuan
*/
@RestController
@RequestMapping("/system")
@Api(tags = "登录的接口类")
public class LoginController {
@Autowired
private IUserService userService;
@Autowired
private RedisTemplate redisTemplate;
@PostMapping("/login")
@ApiOperation(value ="登录接口")
public CommonResult login(@RequestBody LoginVo loginVo){
try{
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(loginVo.getUsername(), loginVo.getPassword());
subject.login(usernamePasswordToken);
Object one = subject.getPrincipal();
String token = UUID.randomUUID().toString();
ValueOperations forValue = redisTemplate.opsForValue();
forValue.set(token,one,24, TimeUnit.HOURS);
return new CommonResult(2000,"登录成功",token);
}catch (Exception e){
return new CommonResult(5000,"登录失败",null);
}
}
@GetMapping("/logout")
public CommonResult logout(HttpServletRequest request){
String token = request.getHeader("token");
if(redisTemplate.hasKey(token)){
redisTemplate.delete(token);
return new CommonResult(2000,"退出成功",null);
}else{
return new CommonResult(5000,"无效的token",null);
}
}
}
测试登录
登录成功后获取用户信息时出现如下得错误
被shiro得拦截器给拦截器了
package com.xzj.system.filter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzj.system.vo.CommonResult;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.springframework.data.redis.core.RedisTemplate;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
/**
* @author xuan
*/
public class LoginFilter extends FormAuthenticationFilter {
private RedisTemplate redisTemplate;
public LoginFilter(RedisTemplate redisTemplate){
this.redisTemplate = redisTemplate;
}
//当登录成功后执行得方法,如果该方法返回false,则执行onAccessDenied
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
HttpServletRequest req = (HttpServletRequest) request;
//请求方式是否为OPTIONS
String method = req.getMethod();
if(method!=null && method.equals("OPTIONS")){
return true;
}
//判断请求头是否有token值
String token = req.getHeader("token");
if(token!=null&& redisTemplate.hasKey(token)){
return true;
}
return false;
}
//未登录时调用该方法? 为什么进入没有登录方法:
// --->第一个请求是OPTIONS,没有携带token 第二个因为前端和后端不是用得同一个session.默认shiro以sessionId为是否登录得标准
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
CommonResult commonResult = new CommonResult(4001,"未登录",null);
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(commonResult);
writer.print(json);
writer.flush();
writer.close();
return false;
}
}
6 主页得布局
<template>
<el-container>
<el-header>
<span id="logo" style="display: inline-block;width: 50%;height: 100%;float: left" >
<a href="https://www.bilibili.com/video/BV14g41197PY/"><img src="../assets/logo.png" height="100%" width="180px"></a>
</span>
<span id="avatar" style="float: right">
<el-dropdown >
<span class="el-dropdown-link" style="margin-top: 10px; display: inline-block;">
<el-avatar ></el-avatar>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="info">个人信息</el-dropdown-item>
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
</el-header>
<el-container>
<el-aside width="200px">
</el-aside>
<el-main>
</el-main>
</el-container>
<el-footer>Footer</el-footer>
</el-container>
</template>
<script>
export default {
name: "Home",
methods:{
getInfo(){
this.$http.get("http://localhost:8808/system/user/getInfo").then(result=>{
console.log(result)
})
}
}
}
</script>
<!--当前vue有效-->
<style>
html,body,#app{
height: 100%;
}
body,#app{
padding: 0px;
margin:0px;
}
.el-container{
height: 100%;
}
.el-header, .el-footer {
background-color: #1F272F;
color: #333;
line-height: 60px;
}
.el-aside {
background-color: #545c64;
color: #333;
line-height: 560px;
}
.el-aside>.el-menu{
border: none;
}
.el-main {
background-color: #E9EEF3;
color: #333;
line-height: 560px;
}
body > .el-container {
margin-bottom: 40px;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
</style>
7 退出
前端
//拉下得触发事件
handleCommand(command){
if (command==='logout'){
this.$http.get("/system/logout").then(result=>{
if(result.data.code===2000){
sessionStorage.clear();
this.$router.push("/login");
}
})
}
}
后端
@GetMapping("/logout")
public CommonResult logout(HttpServletRequest request){
String token = request.getHeader("token");
if(redisTemplate.hasKey(token)){
redisTemplate.delete(token);
return new CommonResult(2000,"退出成功",null);
}
return new CommonResult(5000,"无效得token",null);
}
8 查询左侧菜单
(1)前端
initLeftMenu(){
this.$http.get("/system/permission/leftMenu").then(result=>{
if(result.data.code===2000){
this.leftMenus=result.data.data;
}
})
},
(2)后端
@Controller
@RequestMapping("/system/permission")
public class PermissionController {
@Autowired
private IPermissionService permissionService;
@GetMapping("leftMenu")
public CommonResult leftMenu(HttpServletRequest request){
String token = request.getHeader("token");
return permissionService.findPermissionByUserId(token);
}
}
service 层
package com.xzj.system.service.impl;
import com.xzj.system.entity.Permission;
import com.xzj.system.entity.User;
import com.xzj.system.mapper.PermissionMapper;
import com.xzj.system.service.IPermissionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xzj.system.vo.CommonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* 权限 服务实现类
* </p>
*
* @author xzj
* @since 2022-08-08
*/
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {
@Autowired
private PermissionMapper permissionMapper;
@Autowired
private RedisTemplate redisTemplate;
@Override
public CommonResult findPermissionByUserId(String token) {
//根据token获取用户信息
ValueOperations forValue = redisTemplate.opsForValue();
User o = (User) forValue.get(token);
String id = o.getId();
//根据用户id查询该用户具有得权限。
List<Permission> permissionList = permissionMapper.selectByUserId(id);
//设置层级关系
List<Permission> firstMenus = new ArrayList<>();
for (Permission first:permissionList){
if(first.getPid().equals("1")){
firstMenus.add(first);
}
}
//为一级菜单设置二级菜单
for(Permission first: firstMenus){
first.setChildren(findChildren(permissionList,first.getId()));
}
return new CommonResult(2000,"查询成功",firstMenus);
}
//方法递归
public List<Permission> findChildren(List<Permission> permissionList,String id){
List<Permission> children = new ArrayList<>();
for (Permission p :permissionList){
if (p.getPid().equals(id)){
children.add(p);
}
}
for (Permission child: children){
child.setChildren(findChildren(permissionList,child.getId()));
}
return children;
}
}