前后端分离案例--权限系统(跨域请求)

权限系统:

1、前端:vue + elementui + axios + css + html

2、后端:springboot + mybatis-plus + nybatis + druid + shiro + swagger2 + redis

1、前端界面及按钮事件实现

1.1 登录页面的构建

1.1.1 Login.vue文件

<template>
    <div id="aps">
        <div id="con">
            <!-- 头像 -->
            <div class="avatar_box">
                <el-image :src="avatar" style="border-radius: 50%;width: 100%;height: 100%;">
                    <div slot="placeholder" class="image-slot" >
                        加载中<span class="dot">...</span>
                    </div>
                </el-image>
            </div>
            <el-form :model="loginForm" :rules="rules" ref="loginForm" class="login-ruleForm">
                <el-form-item label="账号" prop="username">
                    <el-input v-model="loginForm.username" style="width: 200px;"></el-input>
                </el-form-item>
                <el-form-item label="密码" prop="password">
                    <el-input type="password" v-model="loginForm.password" style="width: 200px;"></el-input>
                </el-form-item>
                <el-form-item style="margin-left: 0px; text-align: center">
                    <el-button type="primary" size="big">登录</el-button>
                    <!--<el-button @click="register" size="small">注册</el-button>-->
                </el-form-item>
            </el-form>
        </div>
    </div>
</template>

<script>
    export default {
        name: "Login",
        data() {
            return {
                avatar:"",
                loginForm: {
                    username:"",
                    password:""
                },
                rules: {
                    username: [
                        {required: true, message: '请输入账号名称', trigger: 'blur'}
                    ],
                    password: [
                        {required: true, message: '请输入密码', trigger: 'blur'}
                    ]
                },
                registerFormVisible: false,
                registerForm:{},
            }
        },
        methods: {

        }
    }
</script>

<style>
html, body {
    height: 100%;
}
body {
    margin: 0px;
    overflow-x: hidden;
}
#con{
    border: 1px solid gray;
    border-radius: 10px;
    width: 400px;
    height: 280px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    padding: 20px;
    text-align: center;
    background: white;
    opacity:0.8;
}
#aps{
    width: 100%;
    height: 100%;
    background-image: url("../assets/images/background3.jpg");
    background-size: 100% 100%;
    background-position: center center;
    overflow: auto;
    background-repeat: no-repeat;
    position: fixed;
    line-height: 100%;
}
#con>.avatar_box{
    height: 100px;
    width: 100px;
    border: 1px solid #eee;
    border-radius: 50%;
    padding: 10px;
    box-shadow: 0 0 10px #ddd;
    position: absolute;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: #fff;
}
.login-ruleForm {
    position: absolute;
    bottom: 0;
    width: 100%;
    padding: 0 50px;
    box-sizing: border-box;
}
</style>

1.1.2 App.vue

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>

export default {
  name: 'app',
  components: {

  }
}
</script>

<style>

</style>

1.1.3 router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'

import Login from '../views/Login.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    name: 'Login',
    component: Login
  }
]

const router = new VueRouter({
  routes
})

export default router

 1.2 登录按钮事件

如果想在vue工程中使用axios进行异步请求,则需要在main.js中导入axios
[1]//导入axios
import axios from "axios";
[2]//把axios挂载到vue对象中,以后在vue中如果使用axios直接可以用$http名称
Vue.prototype.$http=axios

1.2.1 main.js文件

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挂载到vue对象中,以后在vue中如果使用axios直接可以使用$http名称
Vue.prototype.$http = axios

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

1.2.2 Login.vue文件

在Login.vue文件中点击登录按钮,向后台服务器发送axios异步请求

methods: {
    login(){
        //表单校验
        this.$refs['loginForm'].validate((valid)=>{
            if (valid){
                //url:后端登录接口的路径
                this.$http.post("http://localhost:8080/login",this.loginForm).then(result=>{
                    console.log(result)
                })
            }
        })
    }
}

2、后端登录接口

2.1 pom.xml

<?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.gjx</groupId>
    <artifactId>springboot-vue</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-vue</name>
    <description>springboot-vue</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--引入swagger的启动依赖-->
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
            <version>1.9.1.RELEASE</version>
        </dependency>
        <!--引入swagger的图形界面-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.7.8</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--代码生成器-->
        <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>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.2 mybatis-plus代码生成器

public class CodeGenerator {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://192.168.1.29:3306/acl_permission?serverTimezone=Asia/Shanghai", "root", "990412")
                .globalConfig(builder -> {
                    builder.author("gjx") // 设置作者
                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir(".\\src\\main\\java"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("com") // 设置父包名
                            .moduleName("gjx") // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.xml, ".\\src\\main\\resources\\mapper\\")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude("acl_permission","acl_role","acl_user") // 设置需要生成的表名
                            .addTablePrefix("acl_"); // 设置过滤表前缀
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();

    }
}

 

2.3 配置application文件

server.port=8081
# 配置mysql数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.1.29:3306/acl_permission?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=990412

# mybatis mapper映射文件的路径
mybatis.mapper-locations=classpath:mapper/*.xml

# mybatis-plus的日志文件stdout
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

2.4 前端传递的参数接收类vo包下

2.5 接口

@RestController
public class LoginController {

    @Autowired
    private IUserService iUserService;

    @PostMapping("/login")
    public CommonResult login(@RequestBody LoginVO loginVO){
        User login = iUserService.login(loginVO);
        if (login!=null){
            return new CommonResult(2000,"登录成功",null);
        }
        return new CommonResult(5000,"登录失败",null);
    }
}

2.6 使用swagger2进行接口测试

swagger2配置类

@Configuration
public class SwaggerConfig {

    @Autowired
    Docket docket;
    @Bean
    public Docket docket(){
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.gjx.controller"))
                .build();
        return docket;
    }

    private ApiInfo apiInfo(){

        Contact DEFAULT_CONTACT = new Contact("dumpling", "https://taobao.com", "1983275549@qq.com");
        ApiInfo apiInfo = new ApiInfo("dumpling的接口文档", "关于Student表的一些基本操作", "1.0", "http://192.168.1.29:8080/",
                DEFAULT_CONTACT, "Apache 2.0", "http://192.168.1.29:8080/", new ArrayList<VendorExtension>());
        return apiInfo;
    }
}

测试

3、前端调用后端登录接口

我们会发现报了不支持跨域请求的错误

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

什么是跨域呢?

前端发起请求的域与该请求指向的资源所在的域不一样,凡是发送请求的url的 协议、域名、端口号三者之间任意一者与当前页面地址不同的请求。这里的域指的是这样的一个概念:我们认为若协议 + 域名 + 端口号均相同,那么就是同域。

出现了两个请求: 有一个请求的方式为: OPTIONS 和真实的请求方式  

OPTIONS先头部队。---探视后台有没有解决跨域。

解决方法:

1.前端解决

2.后端解决---->这里也有几种方式:  

【1】可以借助nginx.  

【2】在代码中解决

在控制层接口上添加@CrossOrigin ,不过每一个controller文件都许哟啊加上这个注解

这个注解的一些属性

(origins = {"192.168.0.111:8080","192.168.0.120:8081"},allowedHeaders="运行哪些请求头跨域",methods={"GET","POST"})

origins: 允许哪些域可以跨域访问我这个接口
allowedHeaders:允许哪些请求头信息跨域
methods: 允许哪些请求方式跨域

设置一个全局跨域配置类。

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

这个配置类和上面的@CrossOrigin注解两者只能选其一。

4、登录成功后前端路由跳转

 5、将用户会话信息存储在redis中

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

5.1 修改登录的接口

pom.xml文件

<!--引入jedis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置文件

#redis数据库配置
spring.redis.host=localhost
spring.redis.port=6379
@RestController
@Api("登录的接口类")
//@CrossOrigin
public class LoginController {

    @Autowired
    private IUserService iUserService;

    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping("/login")
    @ApiOperation("登录接口")
    public CommonResult login(@RequestBody LoginVO loginVO){
        User login = iUserService.login(loginVO);
        if (login!=null){
            String token = UUID.randomUUID().toString();
            ValueOperations forValue = redisTemplate.opsForValue();
            forValue.set(token,login,24, TimeUnit.HOURS);
            return new CommonResult(2000,"登录成功",token);
        }
        return new CommonResult(5000,"登录失败",null);
    }
}

5.2 修改前端登录方法

 后面每次请求都可以携带该token,每次请求都得要人为添加参数token, 我们可以使用axios得请求拦截器。

在登录成功之后,使用一个按钮测试token是否在请求头中

然后观察后台能否获取token

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值