1.前端使用: vue + elementui + axios + css + html
2.后端使用: springboot+mybatis-plus +mybatis+druid+shiro+swagger2+redis

-
- <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"
- @click="login"
- style="margin-left: 100px;width: 100px">登录el-button>
- el-form-item>
- el-form>
- el-card>
- div>
- export default {
- name: "Login",
- data(){
- return{
- ruleForm: {
- name: '',
- password: ''
- },
- rules: {
- name: [
- {required: true, message:'用户名不能为空', trigger: 'blur'},
- ],
- password: [
- {required: true, message: '密码不能为空', trigger: 'blur'},
- ]
- },
- imgUrl:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202010%2F16%2F20201016234725_52ed2.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1662528624&t=c2ac363744d360cd4d61b7a9ac9cffef'
- }
- },
- methods:{
- login(){
- this.$refs['ruleForm'].validate((valid) => {
- if(valid) {
-
- this.$message.success("登录成功")
- } else {
- this.$message.error("登录失败")
- }
- })
- }
- }
-
-
- }
- #login_box{
- position: relative;
- width: 500px;
- margin: 250px auto;
- background-image: url("../assets/2.jpeg");
- }
- #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;
- }
-




如果想在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=>{
-
- });
- }
- })
- }
- }


- <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.0modelVersion>
- <parent>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-parentartifactId>
- <version>2.3.12.RELEASEversion>
- <relativePath/>
- parent>
- <groupId>com.ykqgroupId>
- <artifactId>qy151-springboot-vueartifactId>
- <version>0.0.1-SNAPSHOTversion>
- <name>qy151-springboot-vuename>
- <description>Demo project for Spring Bootdescription>
- <properties>
- <java.version>1.8java.version>
- properties>
- <dependencies>
-
- <dependency>
- <groupId>com.baomidougroupId>
- <artifactId>mybatis-plus-generatorartifactId>
- <version>3.5.2version>
- dependency>
- <dependency>
- <groupId>org.freemarkergroupId>
- <artifactId>freemarkerartifactId>
- <version>2.3.31version>
- dependency>
-
- <dependency>
- <groupId>com.baomidougroupId>
- <artifactId>mybatis-plus-boot-starterartifactId>
- <version>3.5.2version>
- dependency>
- <dependency>
- <groupId>com.alibabagroupId>
- <artifactId>druid-spring-boot-starterartifactId>
- <version>1.2.8version>
- dependency>
-
- <dependency>
- <groupId>com.github.xiaoymingroupId>
- <artifactId>swagger-bootstrap-uiartifactId>
- <version>1.9.6version>
- dependency>
- <dependency>
- <groupId>com.spring4allgroupId>
- <artifactId>swagger-spring-boot-starterartifactId>
- <version>1.9.1.RELEASEversion>
- dependency>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
- <dependency>
- <groupId>org.mybatis.spring.bootgroupId>
- <artifactId>mybatis-spring-boot-starterartifactId>
- <version>2.2.2version>
- dependency>
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <scope>runtimescope>
- dependency>
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- <optional>trueoptional>
- dependency>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-testartifactId>
- <scope>testscope>
- dependency>
- dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-maven-pluginartifactId>
- <configuration>
- <excludes>
- <exclude>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- exclude>
- excludes>
- configuration>
- plugin>
- plugins>
- build>
-
- project>
- package com.qy151;
-
- import com.baomidou.mybatisplus.generator.FastAutoGenerator;
- import com.baomidou.mybatisplus.generator.config.OutputFile;
- import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
-
- import java.util.Collections;
-
- /**
- * TODO
- *
- * @author DELL
- * @version 1.0
- * @since 2022-07-25 19:07:17
- */
- public class Generator {
- public static void main(String[] args) {
- FastAutoGenerator.create("jdbc:mysql://localhost:3306/shiropermission?serverTimezone=Asia/Shanghai", "root", "root")
- .globalConfig(builder -> {
- builder.author("YSH") // 设置作者
- .enableSwagger() // 开启 swagger 模式
- .fileOverride() // 覆盖已生成文件
- .outputDir(".\\src\\main\\java\\"); // 指定输出目录
- })
- .packageConfig(builder -> {
- builder.parent("com.qy151") // 设置父包名
- .moduleName("system") // 设置父包模块名
- .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "src\\main\\resources\\mapper\\")); // 设置mapperXml生成路径
- })
- .strategyConfig(builder -> {
- builder.addInclude("acl_role_permission","acl_user","acl_role","acl_permission")// 设置需要生成的表名
- .addTablePrefix("acl_"); // 设置过滤表前缀
- })
- .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
- .execute();
-
- }
- }
- server.port=8809
-
- spring.datasource.druid.url=jdbc:mysql://localhost:3306/shiropermission?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
注意:
如果遇到下面错误:

报错:创建名为'userServiceImpl'的bean时出错:注入自动连接的依赖项失败; 嵌套异常是org.springframework.beans.factory.BeanCreationException:无法自动装配字段
改配置之前是可以正常运行的 这种报错提示很明确问题在那个类,但范围比较大,根据这个类错误可能性排查一下,如果能记录能报错具体位置就更好了。
原因:

切记主启动类上一定要加上
出现以下错误:

为跨域问题:
当使用异步请求从一个网址访问另一个网址时可能会出现跨域问题。
前提:
1. 必须为异步请求
2. 当端口号或协议或ip不同时则会出现跨域
出现两个请求: 有一个请求的方式为: OPTIONS 和真实的请求方式

理解: OPTIONS先头部队。---探视后台有没有解决跨域。
如何解决跨域:
后端解决---->这里也有几种方式:
【1】可以借助nginx.
【2】在代码中解决
在控制层接口上添加@CrossOrigin


(origins = {"192.168.0.111:8080","192.168.0.120:8081"},allowedHeaders="运行哪些请求头跨域",methods={"GET","POST"})
origins: 允许哪些域可以跨域访问我这个接口
allowedHeaders:允许哪些请求头信息跨域
methods: 允许哪些请求方式跨域
上面再控制层接口处加上注解的方式解决跨,麻烦的地方就需要对每个控制类都加该注解。 设置一个全局跨域配置类。
注意:加完配置类记得把接口上的注解去掉

- package com.qy151.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;
-
- @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);
- }
- }

登录成功后前端路由跳转


(1)配置swaager的工具类
- package com.qy151.system.config;
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import springfox.documentation.builders.PathSelectors;
- import springfox.documentation.builders.RequestHandlerSelectors;
- import springfox.documentation.service.ApiInfo;
- import springfox.documentation.service.Contact;
- import springfox.documentation.service.VendorExtension;
- import springfox.documentation.spi.DocumentationType;
- import springfox.documentation.spring.web.plugins.Docket;
-
- import java.util.ArrayList;
-
- /**
- * @Author YSH
- * @Date 2021/4/29 16:37
- * @Version 1.0
- */
- @Configuration
- public class SwaggerConfig {
-
- //获取swagger2的实例对象docket
- @Bean
- public Docket getDocket() {
- Docket docket = new Docket(DocumentationType.SWAGGER_2)
- .groupName("QY151")
- .apiInfo(apiInfo())
- .select()//设置哪些包下的类生产api接口文档
- .apis(RequestHandlerSelectors.basePackage("com.qy151.system.controller"))
- //设置哪些请求路径生产接口文档
- .paths(PathSelectors.any())
- .build();
- return docket;
- }
-
- private ApiInfo apiInfo() {
- Contact DEFAULT_CONTACT = new Contact("YSH", "http://www.bing.com", "1430930278@qq.com");
- ApiInfo apiInfo = new ApiInfo("员工管理系统API接口文档", "员工管理系统API接口文档", "1.0", "http://www.bing.com",
- DEFAULT_CONTACT, "Apache 2.0",
- "http://www.apache.org/licenses/LICENSE-2.0", new
- ArrayList
()); - return apiInfo;
- }
- }
(2)为类加上swaager注解



(3)在主启动类上开启swaager注解

启动时遇到以下问题:

解决方案:

登录成功:

上面咱们写的登录,后端没有保存数据 前端也没有拿到数据进行保存

要用redis的原因是因为如果高并发访问数据库数据库会崩溃,造成系统瘫痪
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-data-redisartifactId>
- dependency>
application配置文件
- #redis服务器的配置
- spring.redis.host=localhost
- spring.redis.port=6379
RedisTemplate类需要序列化,加入一个配置类
- package com.qy151.system.config;
-
- import com.fasterxml.jackson.annotation.JsonAutoDetect;
- import com.fasterxml.jackson.annotation.PropertyAccessor;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.springframework.cache.CacheManager;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.redis.cache.RedisCacheConfiguration;
- import org.springframework.data.redis.cache.RedisCacheManager;
- import org.springframework.data.redis.connection.RedisConnectionFactory;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
- import org.springframework.data.redis.serializer.RedisSerializationContext;
- import org.springframework.data.redis.serializer.RedisSerializer;
- import org.springframework.data.redis.serializer.StringRedisSerializer;
-
- import java.time.Duration;
-
- /**
- * @BelongsProject: 0808-webstorm-vue
- * @BelongsPackage: com.qy151.system
- * @unthor : YSH
- * @date : 2022/8/8 19:25
- * @Description: TODO
- */
- @Configuration
- public class RedisConfig {
- @Bean
- public CacheManager cacheManager(RedisConnectionFactory factory) {
- RedisSerializer
redisSerializer = new StringRedisSerializer(); - Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
- //解决查询缓存转换异常的问题
- ObjectMapper om = new ObjectMapper();
- om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
- om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
- jackson2JsonRedisSerializer.setObjectMapper(om);
- // 配置序列化(解决乱码的问题),过期时间600秒
- RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
- .entryTtl(Duration.ofSeconds(600)) //缓存过期10分钟 ---- 业务需求。
- .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//设置key的序列化方式
- .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //设置value的序列化
- .disableCachingNullValues();
- RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
- .cacheDefaults(config)
- .build();
- return cacheManager;
- }
- @Bean
- public RedisTemplate
redisTemplate(RedisConnectionFactory factory) { - RedisTemplate
template = new RedisTemplate<>(); - RedisSerializer
redisSerializer = new StringRedisSerializer(); - Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
- ObjectMapper om = new ObjectMapper();
- om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
- om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
- jackson2JsonRedisSerializer.setObjectMapper(om);
- template.setConnectionFactory(factory);
- //key序列化方式
- template.setKeySerializer(redisSerializer);
- //value序列化
- template.setValueSerializer(jackson2JsonRedisSerializer);
- //value hashmap序列化 filed value
- template.setHashValueSerializer(jackson2JsonRedisSerializer);
- template.setHashKeySerializer(redisSerializer);
- return template;
- }
- }
- package com.qy151.system.controller;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.qy151.system.entity.User;
- import com.qy151.system.service.IUserService;
- import com.qy151.system.vo.CommonResult;
- import com.qy151.system.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;
-
- /**
- * @BelongsProject: 0811qxglxt
- * @BelongsPackage: com.qy151.system.controller
- * @unthor : YSH
- * @date : 2022/8/11 16:17
- * @Description: TODO
- */
- @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
wrapper = new QueryWrapper<>(); - wrapper.eq("username",loginVo.getName());
- wrapper.eq("password",loginVo.getPassword());
- wrapper.eq("is_deleted",0);
- User one = userService.getOne(wrapper);
- if(one!=null){
- //随机生成一个唯一字符串。
- String token = UUID.randomUUID().toString();
- //把该token作为redis的key value为当前登录用户信息
- ValueOperations forValue = redisTemplate.opsForValue();
- forValue.set(token,one,24, TimeUnit.HOURS);
- return new CommonResult(2000,"登录成功",token);
- }else{
- return new CommonResult(5000,"登录失败",null);
- }
-
- }
-
- }

由于每次前端都往后端请求都得要人为添加参数token. 我们可以使用axios得请求拦截器。

- //设置axios得请求拦截器---在请求头上添加token
- axios.interceptors.request.use(config=>{
- //从sessionStorage获取token值
- var token = sessionStorage.getItem("token");
- if(token){ //token不为空则为真
- //请求头中会携带token
- config.headers.token=token;
- }
- return config;
- })

前端方法:
- <template>
- <div>
- <el-button type="primary" @click="getInfo">获取用户信息el-button>
- div>
- template>
-
- <script>
- export default {
- name: "User",
- methods:{
- getInfo(){
- this.$http.get("http://localhost:8081/system/user/getInfo").then(result=>{
- console.log(result)
- })
- }
- }
- }
- script>
-
- <style scoped>
-
- style>
后端接口:
- package com.qy151.system.controller;
-
-
- import com.qy151.system.entity.User;
- import com.qy151.system.vo.CommonResult;
- import io.swagger.annotations.Api;
- 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.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RestController;
-
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
-
- /**
- *
- * 用户表 前端控制器
- *
- *
- * @author YSH
- * @since 2022-08-11
- */
- @RestController
- @RequestMapping("/system/user")
- @Api(tags = "用户接口类")
- public class UserController {
- @Autowired
- private RedisTemplate redisTemplate;
-
- @GetMapping("getInfo")
- public CommonResult getInfo(HttpServletRequest request){
- String token = request.getHeader("token");
- System.out.println(token);
- //根据token从redis中获取用户信息
- ValueOperations forValue = redisTemplate.opsForValue();
- User o = (User) forValue.get(token);
- return new CommonResult(2000,"获取用户信息成功",o);
- }
- }

前置路由守卫:就是在路由跳转前加上自己得一些业务代码,在main.js中配置。类似于拦截器
- //设置前置路由守卫 to:到哪个路由 from:从哪个路由来 next():放行到指定路由
- router.beforeEach((to,from,next)=>{
- //获取跳转得路径
- var path = to.path;
- //判断是否为登录路由路径
- if(path==="/login"){
- console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
- //放行
- return next();
- }
- //其他路由路径 判断是否登录过
- var token = sessionStorage.getItem("token");
- if(token){
- return next();
- }
- //跳转登录
- return next("/login");
- })

- <dependency>
- <groupId>org.apache.shirogroupId>
- <artifactId>shiro-spring-boot-starterartifactId>
- <version>1.7.0version>
- dependency>
- package com.qy151.system.config;
-
-
- import com.qy151.system.filter.LoginFilter;
- import com.qy151.system.realm.MyRealm;
- 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;
-
- /**
- * @BelongsProject: 0805-springboot-shiro
- * @BelongsPackage: com.qy151.config
- * @unthor : YSH
- * @date : 2022/8/5 18:52
- * @Description: TODO
- */
- @Configuration //交于容器管理
- public class ShiroConfig {
-
-
- //安全认证
- @Bean
- public DefaultWebSecurityManager securityManager(){
- DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
- securityManager.setRealm(realm());
- return securityManager;
-
- }
-
-
-
- //安全数据源 自定义realm
- @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;
-
- //shiro过滤器工厂 设置过滤的规则
- @Bean(value = "shiroFilter")
- public ShiroFilterFactoryBean filterFactoryBean(){
- ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
- factoryBean.setSecurityManager(securityManager());
-
- //设置拦截规则
- HashMap
map=new HashMap<>(); - map.put("/system/login","anon");
- map.put("/doc.html","anon");
- map.put("/swagger-ui.html","anon");
- map.put("/swagger/**","anon");
- map.put("/webjars/**", "anon");
- map.put("/swagger-resources/**","anon");
- map.put("/v2/**","anon");
- map.put("/static/**", "anon");
-
- map.put("/**","authc");
-
-
-
- factoryBean.setFilterChainDefinitionMap(map);
-
- //设置自定义认证过滤器
- HashMap
filterMap=new HashMap(); - filterMap.put("authc",new LoginFilter(redisTemplate));
- factoryBean.setFilters(filterMap);
-
- return factoryBean;
- }
-
-
- //注册filter
- @Bean
- public FilterRegistrationBean
filterRegistrationBean(){ - FilterRegistrationBean
filterRegistrationBean=new FilterRegistrationBean<>(); - filterRegistrationBean.setName("shiroFilter");
- filterRegistrationBean.setFilter(new DelegatingFilterProxy());
- filterRegistrationBean.addUrlPatterns("/*");
- 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;
- }
-
- }
- package com.qy151.system.realm;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.qy151.system.entity.User;
- import com.qy151.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;
-
- /**
- * @BelongsProject: 0805-springboot-shiro
- * @BelongsPackage: com.qy151.realm
- * @unthor : YSH
- * @date : 2022/8/5 18:57
- * @Description: TODO
- */
- public class MyRealm extends AuthorizingRealm {
- @Autowired
- private IUserService userService;
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
- return null;
- }
-
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
- String username = (String) token.getPrincipal();
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.eq("username",username);
- wrapper.eq("is_deleted",0);
- User user = userService.getOne(wrapper);
- if(user!=null){
- ByteSource bytes = ByteSource.Util.bytes(user.getSalt());
- SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),bytes,this.getName());
- return info;
- }
- return null;
- }
- }
- package com.qy151.system.controller;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.qy151.system.entity.User;
- import com.qy151.system.service.IUserService;
- import com.qy151.system.vo.CommonResult;
- import com.qy151.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 java.util.UUID;
- import java.util.concurrent.TimeUnit;
-
- /**
- * @BelongsProject: 0811qxglxt
- * @BelongsPackage: com.qy151.system.controller
- * @unthor : YSH
- * @date : 2022/8/11 16:17
- * @Description: TODO
- */
- @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.getName(), loginVo.getPassword(),loginVo.getSalt());
- 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);
- }
- }
-
- }


登录成功后获取用户信息时出现如下得错误

被shiro得拦截器给拦截器了。
- package com.qy151.system.filter;
-
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.qy151.system.vo.CommonResult;
- import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.redis.core.RedisTemplate;
-
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServletRequest;
- import java.io.PrintWriter;
-
- /**
- * @BelongsProject: 0805-springboot-shiro
- * @BelongsPackage: com.qy151.filter
- * @unthor : YSH
- * @date : 2022/8/5 19:19
- * @Description: TODO
- */
- //如果类没有交于spring容器来管理 那么该类中得属性也不能让spring帮你注入
- public class LoginFilter extends FormAuthenticationFilter {
-
- @Autowired
- private RedisTemplate redisTemplate; //LoginFilter必须交于spring容器来管理。
-
- public LoginFilter(RedisTemplate redisTemplate) {
- this.redisTemplate = redisTemplate;
- }
-
- //当登录成功后执行的方法 如果该方法返回false 则执行onAccessDenied
- @Override
- protected boolean isAccessAllowed(ServletRequest request,ServletResponse response,Object mappedValue){
- System.out.println(redisTemplate);
- 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;
- }
-
- //返回true则表示登录 返回false则表示未登录
- System.out.println("=====================");
- 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); //响应给客户json数据
- writer.flush();
- writer.close();
- return false;
- }
- }

- <el-container>
- <el-header>
- <div id="logo" style="display: inline-block;width:50%;height: 100%;float: left" >
- <img src="../assets/1.jpg" height="100%">
- div>
- <span id="avatar" style="float: right">
- <el-dropdown @command="handleCommand">
- <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-menu
- default-active="2"
- class="el-menu-vertical-demo"
- background-color="darkgrey"
- text-color="#fff"
- :router="true"
- unique-opened="unique-opened"
- active-text-color="#ffd04b">
- el-menu>
- el-aside>
- <el-main>
- <router-view/>
- el-main>
- el-container>
- el-container>
- template>
-
- <script>
- export default {
- name: "User",
- methods:{
- getInfo(){
- this.$http.get("http://localhost:8809/system/user/getInfo").then(result=>{
- console.log(result)
- })
- }
- }
- }
- script>
-
- <style>
- html, body, #app {
- height: 100%;
- }
-
- body, #app {
- padding: 0px;
- margin: 0px;
- }
-
- .el-container {
- height: 100%;
- }
-
- .el-header, .el-footer {
- background-color: grey;
- color: #333;
- line-height: 60px;
- }
-
- .el-aside {
- background-color: darkgrey;
- color: #333;
- line-height: 560px;
- }
-
- .el-aside > .el-menu {
- border: none;
- }
-
- .el-main {
- background-color: lightgrey;
- color: darkolivegreen;
- }
-
- 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>

由于每个跳转都需要写ip和端口,我们可以在main.js中设置axios的基础路径
//设置axios基础路径 axios.defaults.baseURL="http://localhost:8809"

- @GetMapping("logout")
- @ApiOperation(value = "退出接口")
- 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,"退出失败",null);
- }
- initLeftMenu(){
- this.$http.get("/system/permission/leftMenu").then(result=>{
- if(result.data.code===2000){
- this.leftMenus=result.data.data;
- }
- })
- },


- package com.qy151.system.controller;
-
-
- import com.qy151.system.service.IPermissionService;
- import com.qy151.system.vo.CommonResult;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RestController;
-
- import javax.servlet.http.HttpServletRequest;
-
- /**
- *
- * 权限 前端控制器
- *
- *
- * @author YSH
- * @since 2022-08-11
- */
- @RestController
- @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);
- }
- }
- package com.qy151.system.service;
-
- import com.qy151.system.entity.Permission;
- import com.baomidou.mybatisplus.extension.service.IService;
- import com.qy151.system.vo.CommonResult;
-
- /**
- *
- * 权限 服务类
- *
- *
- * @author YSH
- * @since 2022-08-11
- */
- public interface IPermissionService extends IService
{ -
- CommonResult findPermissionByUserId(String token);
- }
- package com.qy151.system.service.impl;
-
- import com.qy151.system.entity.Permission;
- import com.qy151.system.entity.User;
- import com.qy151.system.mapper.PermissionMapper;
- import com.qy151.system.service.IPermissionService;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.qy151.system.service.IRolePermissionService;
- import com.qy151.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;
-
- /**
- *
- * 权限 服务实现类
- *
- *
- * @author YSH
- * @since 2022-08-11
- */
- @Service
- public class PermissionServiceImpl extends ServiceImpl
implements IPermissionService { -
- @Autowired
- private PermissionMapper permissionMapper;
- @Autowired
- private RedisTemplate redisTemplate;
-
- @Autowired
- private IRolePermissionService rolePermissionService;
-
- @Override
- public CommonResult findPermissionByUserId(String token) {
- //根据token获取用户信息
- ValueOperations forValue = redisTemplate.opsForValue();
- User o = (User) forValue.get(token);
- String id = o.getId();
- //根据用户id查询该用户具有得权限。
- List
permissionList = permissionMapper.selectByUserId(id); - //设置层级关系
- List
firstMenus = new ArrayList<>(); - for (Permission first : permissionList) {
- //int
- if (first.getPid().equals("1")) {
- firstMenus.add(first);
- }
- }
-
-
- //为一级菜单设置二级菜单
- for (Permission first : firstMenus) {
- //根据一级菜单id 查询 该菜单得二级菜单。如果出现不确定有几级菜单 那么我们可以使用方法得递归调用
- first.setChildren(findChildren(permissionList, first.getId()));
-
- }
-
- return new CommonResult(2000,"查询成功",firstMenus);
- }
-
- //方法递归
- private List
findChildren(List permissionList, String id) { - List
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;
-
- }
- }

- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.qy151.system.mapper.PermissionMapper">
-
- <select id="selectByUserId" resultType="com.qy151.system.entity.Permission">
- select distinct p.* from acl_user_role ur join acl_role_permission rp on ur.role_id=rp.role_id join acl_permission p
- on rp.permission_id = p.id where ur.user_id=#{userid} and type=1 and rp.is_deleted=0
- </select>
- </mapper>


- <template>
- <div class="navMenu">
-
- <template v-for="navMenu in menuData">
-
- <el-menu-item v-if="navMenu.children.length==0"
- :index="navMenu.path"
- >
- <i :class="navMenu.icon">i>
- <span slot="title">{{navMenu.name}}span>
- el-menu-item>
-
-
- <el-submenu v-if="navMenu.children.length!=0"
- :index="navMenu.path">
- <template slot="title">
- <i :class="navMenu.icon">i>
- <span> {{navMenu.name}}span>
- template>
-
- <LeftMenu :menuData="navMenu.children">LeftMenu>
- el-submenu>
- template>
-
- div>
- template>
-
- <script>
- export default {
- name: 'LeftMenu',
- //接受使用者传递的数据
- props: ['menuData'],
- data() {
- return {}
- },
- methods: {}
- }
- script>
-
- <style>
- style>

查询全部角色信息时,添加了分页插件
插件的配置类:

- package com.qy151.system.config;
-
- import com.baomidou.mybatisplus.annotation.DbType;
- import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
- import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- @Configuration
- public class MybatisPlusConfig {
-
- /**
- * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
- */
- @Bean
- public MybatisPlusInterceptor mybatisPlusInterceptor() {
- MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
- return interceptor;
- }
-
- }

- @PostMapping("findRole/{currentPage}/{pageSize}")
- @ApiOperation(value = "查询接口")
- public CommonResult findRole(@PathVariable Integer currentPage, @PathVariable Integer pageSize, @RequestBody RoleVo roleVo){
- return roleService.selectRole(currentPage,pageSize,roleVo);
- }
CommonResult selectRole(Integer currentPage, Integer pageSize, RoleVo roleVo);
- @Autowired
- private RoleMapper roleMapper;
-
- @Override
- public CommonResult selectRole(Integer currentPage, Integer pageSize, RoleVo roleVo) {
- Page
page = new Page<>(currentPage,pageSize); -
- QueryWrapper
wrapper = new QueryWrapper<>(); -
- if (StringUtils.hasText(roleVo.getRoleName())){
- wrapper.like("role_name",roleVo.getRoleName());
- }
-
- if (StringUtils.hasText(roleVo.getStartDate())){
- wrapper.ge("gmt_create",roleVo.getStartDate());
- }
-
- if (StringUtils.hasText(roleVo.getEndDate())){
- wrapper.le("gmt_create",roleVo.getEndDate());
- }
-
- roleMapper.selectPage(page,wrapper);
-
- return new CommonResult(2000,"查询成功",page);
- }



- package com.qy151.system.controller;
-
-
- import com.qy151.system.service.IRolePermissionService;
- import com.qy151.system.vo.CommonResult;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
-
- import org.springframework.stereotype.Controller;
-
- import java.util.List;
-
- /**
- *
- * 角色权限 前端控制器
- *
- *
- * @author YSH
- * @since 2022-08-11
- */
- @RestController
- @RequestMapping("/system/role-permission")
- public class RolePermissionController {
-
- @Autowired
- private IRolePermissionService rolePermissionService;
-
- @PostMapping("{roleid}")
- public CommonResult fenQuanXian(@PathVariable String roleid,@RequestBody List
ids) { - return rolePermissionService.fen(roleid,ids);
- }
- }
- package com.qy151.system.service;
-
- import com.qy151.system.entity.RolePermission;
- import com.baomidou.mybatisplus.extension.service.IService;
- import com.qy151.system.vo.CommonResult;
-
- import java.util.List;
-
- /**
- *
- * 角色权限 服务类
- *
- *
- * @author YSH
- * @since 2022-08-11
- */
- public interface IRolePermissionService extends IService
{ -
-
- CommonResult fen(String roleId, List
ids) ; - }
- package com.qy151.system.service.impl;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.qy151.system.entity.RolePermission;
- import com.qy151.system.mapper.RolePermissionMapper;
- import com.qy151.system.service.IRolePermissionService;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.qy151.system.vo.CommonResult;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
-
- import java.time.LocalDateTime;
- import java.util.List;
- import java.util.stream.Collectors;
-
- /**
- *
- * 角色权限 服务实现类
- *
- *
- * @author YSH
- * @since 2022-08-11
- */
- @Service
- public class RolePermissionServiceImpl extends ServiceImpl
implements IRolePermissionService { -
- @Override
- @Transactional
- public CommonResult fen(String roleid, List
ids) { - //删除roleid 对应的权限
- QueryWrapper
wrapper =new QueryWrapper<>(); - wrapper.eq("role_id",roleid);
- this.remove(wrapper);
- //添加新选中的权限
- List
collect = ids.stream().map(item -> new RolePermission(null, roleid, item, 0, LocalDateTime.now(), LocalDateTime.now())) - .collect(Collectors.toList());
- this.saveBatch(collect);
- return new CommonResult(2000,"修改权限成功",null);
- }
-
-
-
- }

