springboot-vue前后端分离登录

目录

 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;
   }
}

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Springboot Vue 前后端分离登录注册代码可以通过使用RESTful API来实现,它可以帮助前端和后端之间的数据传输。后端可以使用Spring Boot框架来构建RESTful API,而前端则可以使用Vue.js来调用后端API实现登录或注册。 ### 回答2: Spring BootVue.js是非常流行的前后端分离框架,可以很方便地进行登录注册功能的开发。 在后端Spring Boot中,首先需要创建一个UserController类来处理用户相关的请求,包括注册和登录。在UserController中,我们可以定义两个POST请求的接口,一个用于用户注册,一个用于用户登录。 用户注册接口可以接收一个User对象作为参数,User对象包含了用户的用户名和密码等信息。在用户注册接口中,我们可以先检查数据库中是否存在相同用户名的用户,如果不存在,则可以将用户信息保存到数据库中,并返回相应的注册成功提示。 用户登录接口可以接收一个LoginRequest对象作为参数,LoginRequest对象包含了用户输入的用户名和密码。在用户登录接口中,我们可以通过用户名在数据库中查询对应的用户信息,然后比对密码是否正确,如果正确则返回登录成功的提示,否则返回登录失败的提示。 在前端Vue.js中,我们可以使用axios库来发送HTTP请求,调用后端提供的接口。在注册页面,可以通过表单获取用户输入的用户名和密码,并发送POST请求到后端的注册接口。在登录页面,也是通过表单获取用户输入的用户名和密码,并发送POST请求到后端登录接口。 后端返回的响应可以根据具体需求进行处理,比如注册成功后可以跳转到登录页面,登录成功后可以跳转到主页。 总结起来,通过Spring Boot提供的后端接口和Vue.js提供的前端页面,前后端分离登录注册功能可以很方便地实现。以上是一个简单的示例,实际的实现会根据具体需求和业务逻辑而有所不同。 ### 回答3: springboot是一个应用程序框架,而vue是一个用于构建用户界面的前端框架。在前后端分离的架构中,前后端分别使用不同的技术进行开发,并通过接口进行通信。下面是一个简单示例的登录注册代码: 后端(使用springboot): 1. 创建一个UserController类,用于处理与用户相关的请求。 2. 在该类中,创建登录和注册的接口,分别对应/login和/register路径。 3. 在登录接口中,获取前端传来的用户名和密码,并与数据库中的用户信息进行比较。若比对成功,则返回成功信息;否则返回失败信息。 4. 在注册接口中,获取前端传来的用户名和密码,并将用户信息存入数据库。 5. 使用spring security等权限管理框架,对接口进行安全验证,确保只有经过认证的用户才能访问。 前端(使用vue): 1. 创建一个Login.vue和Register.vue组件,分别用于登录和注册界面的展示。 2. 在组件中,创建表单,用于用户输入用户名和密码。 3. 在提交按钮点击事件中,使用axios等库,将用户输入的信息发送给后端登录或注册接口。 4. 根据接口返回的结果,在前端展示登录或注册成功或失败的信息。 总结: 以上代码只是一个简单示例,实际开发中可能涉及更多功能的实现。通过springbootvue前后端分离架构,可以实现页面与后端数据的分离,提升开发效率和灵活性。为了保证系统安全性,还需要加入权限管理等措施。这里只提供了一个基本的框架,具体的实现和功能可以根据需求进行扩展和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值