前面已经完成了Vue登录第1版,仅仅是使用JS进行了前端登录验证。下面将在第1版的基础上,使用SpringBoot完成后端程序,通过状态码的传输实现登录认证。这里称其为Vue登录第2.1版。
Vue登录第2.1版采用传输状态码的形式进行登录认证,具体是:
(1)使用Vue完成登录界面,用户输入用户名和密码,向后端程序发送登录请求,并将输入的用户名和密码一起发送到后端程序。
(2)后端程序接受发送的用户名和密码,与事先给出的用户名为“admin”和密码为“123456”,然后进行登录验证。
(3)如果用户输入的用户名和密码与事先设置的用户名和密码相等,返回一个登录成功的状态码;如果都为空,提示输入用户名和密码;如果不相等,则提示用户名或密码错误,则返回一个不成功的状态码。
(4)前端接受状态码,登录成功,则返回灯塔的主界面;不成功,则发出提示信息。
下面分前端程序和后端程序进行讲解。
2.2 Vue登录第2.1版前端程序
Vue登录第2.1版前端程序采用Vue登录第1版的程序,因为要向后端程序发送请求,并接受返回的数据,需要修改main.js和Login.vue这两个文件。
2.2.1 在main.js文件中增加axios库
在main.js文件中增加axios库之前,先复习一下跨域这个知识点。
什么是跨域?
要了解跨域,先要说说同源策略。同源策略是由 Netscape 公司提出的一个安全策略,其含义简单地说:为了保证浏览器的安全,不同源的客户端脚本在没有明确授权的情况下,是不能读写对方资源的。可以这么说同源策略是浏览器安全的基石。这里的同源是指域名、协议和端口相同的资源。当页面在执行一个脚本时会检查访问的资源是否同源,如果非同源,那么在请求数据时,浏览器会报送一个异常,提示拒绝访问。
为了更好地理解同源,下面用一个例子进行说明:
判断下面的资源或URL与 http://www.a.com/dir/index.html 是否同源的?
http://www.a.com/dir1/index2.html,协议、域名和端口(都是80端口),故同源。
http://www.b.com/dir/index.html,域名不同,不同源。
https://www.a.com/index.html, 不同的协议(https,http),故不同源。
http://www.a.com:8080/dir/index.html,不同的端口(一个是80,一个是8080),故不同源。
理解了同源策略,对什么是跨域,就很清楚了。所谓跨域就是指的是从一个域名去请求另外一个域名的资源,即跨域名请求。但浏览器的同源策略这一安全基石是不允许的。
为了解决浏览器跨域请求的问题,W3C提出了跨域资源共享方案(Cross-origin resource sharing,CORS)。下面的几篇博客关于跨域说得更详细。
https://blog.csdn.net/qq_38128179/article/details/84956552。
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS。
https://www.jianshu.com/p/f880878c1398。
https://www.jb51.net/article/161075.htm。
前后端分离的系统中,前端的URL地址和后端的URL地址是不同源的,涉及到跨域请求。
在Vue前端中,可以增加axios库来解决。
在SpringBoot项目中,可以通过配置添加CORS跨域来解决,后面就会加以介绍。
下面首先在Vue前端增加axios库。
在src目录下的main.js文件中,增加axios库进行发送跨域请求,具体代码如下:
程序清单2.1 main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
//等效于:
// import router from './router/index.js'
// 导入全局样式表
import '@/assets/css/global.css'
// 引用axios库,向服务器端发送请求,等同于:
// import axios from 'axios'
var axios = require('axios')
// 设置请求的接口,简单地说就是发送请求的URL地址
axios.defaults.baseURL = 'http://localhost:8082/'
// 将axios挂载到vue原型身上即全局注册,
// 之后可在其他组件中通过this.$axios发送数据
Vue.prototype.$axios = axios
// 设置为“false” 用于关闭生产模式下给出的提示
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
2.2.2 修改登录视图文件Login.vue
在src目录下,修改views视图目录下的登录视图文件Login.vue,使用this.$axios库向后端程序发送登录请求。具体代码如下:
程序清单2.2 Login.vue
<template lang="">
<div class="login" id="login">
<div class="input-wrap">
<label for="male">账 号:</label>
<input type="text" v-model="username" placeholder="请输入账号"/>
</div>
<div class="input-wrap">
<label for="male">密 码:</label>
<input type="password" v-model="password" placeholder="请输入密码"/>
</div>
<div class="input-wrap">
<!-- <button v-on:click="login">登录账号</button> -->
<button @click="login">登录</button>
<button @click="login">注册</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
username: "",
password: "",
};
},
methods: {
login() {
const { username, password } = this;
// 等同于如下语句:
// const username = this.username
// const password = this.password
if (username.length == 0 || password.length == 0) {
alert("请输入用户名或密码!");
return;
}
// 发送登录请求
this.$axios
.post("/login", {
username: username,
password: password,
})
.then((resp) => {
console.log(resp);
let code = resp.data.code;
// alert(code)
if (code === 200) {
alert("登录成功!");
this.$router.push({ path: "/index" });
} else {
alert("登录失败!");
}
});
},
},
};
</script>
<style>
.login {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 300px;
height: 80px;
padding: 10px;
margin: auto;
/*margin: 20% auto;*/
}
.input-wrap {
margin: 20px auto;
}
</style>
2.2.3 前端程序的运行
前端程序还是Vue登录第1版的程序,只是修改了以上几个文件,运行与Vue登录第1版一样,在终端中运行命令:npm run serve,此处省略。
2.3 Vue登录第2.1版后端程序
Vue登录第2.1版后端程序采用SpringBoot来实现。
关于如何创建SpringBoot项目的博客太多,有的写得很用心,这里推荐几篇,大家可参考。
https://blog.csdn.net/sunnyzyq/article/details/108666480。
https://blog.csdn.net/qq_26071319/article/details/106209405。
下面简要介绍灯塔管理系统Vue登录第2.1版后端程序创建过程。
2.3.1 创建后端项目lighthouse-code
打开IDEA 2020.3.1编辑器,如图1是打开创建项目的界面。
图1
在图1中单击按钮【New Project】,打开新建项目的窗口,如图2所示。
图2
在图2的左边选择【Spring Initializr】,右边保持Default,单击按钮【Next】,打开图3所示的界面。
注:如果网络情况不好,可以选择右边的定制【Custom】,在地址栏输入:https://start.aliyun.com/,点击 “Next”,也可以完成SpringBoot项目的创建。还可以在https://start.spring.io/网上生成项目信息后,下载到本地磁盘打开,此处省略。
图3
图3中几个地方的说明如下。
Group:项目组织的唯一标识符,一般采用域名的反写。比如:这里我填写的是com.solo,com是域名,solo是根据自己的爱好而取得,很早很早以前就觉得写程序的人就像一个孤独的舞者,故而取了solo。
Artifact:项目的名称,唯一标识符。注意只能小写,可以用短划线连接单词,试图用数字肯定通不过。
在图3中,单击按钮【Next】,打开图4所示的界面。
图4
在图4中,可以增加依赖包,也就是相当于在pom.xml配置依赖关系。只不过这个是图形界面的。在图中,单击按钮【Next】,打开图5所示的界面。
图5
在图5中,显示了创建后端程序项目命名、保存的路径等信息。在图中,单击按钮【Next】,打开图6所示的界面。
图6
在图6中,是后端程序的整个基础结构。左边是项目的文件目录,中间是左边对应的源文件,右边是Maven的结构。
下面重点分析左边文件的目录结构和几个重点的文件。为了清楚起见,将左边的图单独截取出来进行说明,如图7所示。
图7
图7中的目录结构和文件都是前面自动创建的。这里重点说明几个。
(1)pom.xml:这是用Maven管理项目的配置文件,简单地说,项目中会用到很多jar包,通过这个配置文件引入其坐标,Maven就会帮我们去下载安装,不需要我们手动去添加。关于其详细配置,其官网https://maven.apache.org/pom.html说得非常详细。
(2)src文件目录:保存源代码的文件夹,包含了两个子目录main和test,前面一个是开发最主要的代码,后面一个是测试用的。在main目录中,包含java和resource。
(3)java目录:存放包和java源代码的地方。com.solo就是上面创建的包名,还可以在它的下面在创建若干个子包,在包和子包下创建java类文件,这是java的基础知识,省略。在java下面还有一个LighthouseCodeApplication.java文件,这个在下面单独说明。
(4)resource目录:存放资源文件的地方。由于是前后端分离项目,这里的两个文件夹static和templates都不会用到。在resource目录下还有一个application.properties配置文件, 这个在下面单独说明。
(5)LighthouseCodeApplication.java:这是一个程序启动类,程序唯一的入口。每次创建SpringBoot项目时,都会自动创建这个文件,名称为*Application.java,星号*为项目名称,其中首字母大写,如多个单词,则每个单词的首字母都要大写。这个启动类或入口类有一个main方法,它其实就是一个标准的Java应用程序的入口方法。在main方法中使用SpringApplication.run()启动SpringBoot应用项目。LighthouseCodeApplication.java最基本的代码如程序清单2.3。
程序清单2.3 LighthouseCodeApplication.java
package com.solo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LighthouseCodeApplication {
public static void main(String[] args) {
SpringApplication.run(LighthouseCodeApplication.class, args);
}
}
程序清单2.3 LighthouseCodeApplication.java在SpringBoot应用程序中有两个作用:第一个是完成组件扫码和自动配置;第二个是启动应用程序运行。
第6行:@SpringBootApplication开启Spring的组件扫码和SpringBoot自动配置功能,是SpringBoot的核心注解。
第9行:负责启动引导应用程序。
(6)application.properties:这是一个配置文件,每次创建SpringBoot项目时,都会自动创建这个文件。关于这个文件后面还会继续讲解,此处省略。
到此,完成了创建后端项目lighthouse-code,可以直接运行LighthouseCodeApplication.java,此处省略。
下面提供几篇博客和书籍。
https://spring.io/guides
https://spring.io/projects/spring-boot
https://maven.apache.org/pom.html。
https://www.javatpoint.com/spring-boot-application。
https://blog.csdn.net/qq_45173404/article/details/108627349。
https://spring.io/guides
https://spring.io/projects/spring-boot
《Spring实战》、《Spring Boot实战》、《JavaEE开发的颠覆者:Spring Boot实战》。
接下来在此基础上,开始完成灯塔管理系统Vue登录第2.1版的后端程序。
2.3.2 创建Vue登录第2.1版的后端程序的包结构
灯塔管理系统是以前做项目使用的一个脚手架,最早是基于SSH框架的项目开发,经历过Spring MVC和SpringBoot项目的开发,这次为了写博客,抽取其中权限部分,总的架构如图8所示。
图8
图8中有关包的说明如下:
(1)com.solo下面的base包用于存放系统基础的部分。base包下面包括rbac和security包,前者用于权限管理,后者用于数据安全传输等。
(2)com.solo下面的common包用于存放工具类和配置的部分。common包下面包含config和utils包,前者用于配置跨域等,后者是一些工具类。
2.3.3 pom.xml
由于目前没有引入其他依赖关系,还是保持创建项目的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.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- 项目信息的配置 -->
<groupId>com.solo</groupId>
<artifactId>lighthouse-code</artifactId>
<version>2.1.0</version>
<name>lighthouse-code</name>
<description>lighthouseV2.1</description>
<properties>
<java.version>1.8</java.version>
</properties>
<!-- 定义项目的依赖关系,后面添加依赖关系,就在这里面增加 -->
<dependencies>
<!-- 自动配置模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
</plugin>
</plugins>
</build>
</project>
2.3.4 在application.properties配置端口
application.properties是SpringBoot的一个全局配置文件,其作用是修改SpringBoot自动配置的默认值,比如:服务器的端口、日志、数据源等。本次只配置服务器的端口号,具体如下:
#配置服务器的端口号
server.port=8082
注意:.properties配置文件的格式,采用的等号=赋值的形式,等号左边是配置属性的名称,等号右边是值。
配置文件除了支持.properties后缀名外,还支持.yml后缀名的配置文件。
2.3.5 修改LighthouseCodeApplication.java
尽管运行LighthouseCodeApplication.java后,能够提示系统是否运行成功的信息,但为了更清晰的显示运行是否成功的信息,可以添加一些个性化的输出信息,下面在该文件中增加了一条输出语句,运行成功后,会输出一条“To the Lighthouse......”的信息。
package com.solo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LighthouseCodeApplication {
public static void main(String[] args) {
SpringApplication.run(LighthouseCodeApplication.class, args);
System.out.println("To the Lighthouse......");
}
}
运行该程序,运行结果如图9所示。
图9
2.3.6 在com.solo.base.security下创建LoginDTO
在com.solo.base.security下创建LoginDTO.java类,用于接受用户登录数据传输对象,代码如下:
package com.solo.base.security;
/*
* FileName: LoginDTO.java
* Description: // 用户登录数据传输对象(Data Transfer Object)
* Author: woolflighthouse@163.com
* Date: 2022/2/8 20:54
*/
public class LoginDTO {
/**
* 用户名或登录账户
*/
private String username;
/**
* 密码
*/
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
数据传输对象(Data Transfer Object,DTO),简单地说就是用户封装数据和安全传输数据。这是一种设计模式,而非必须这样做。在下面会了解其使用过程。
2.3.7 配置跨域
在前面已经对跨域进行了说明,在后端程序也需要进行跨域的配置,不然也会发生跨域请求失败的异常。在SpringBoot可以通过@Configuration创建一个配置类来实现。
在com.solo.common.config下创建一个配置类CorsConfig.java来实现,具体代码如下:
package com.solo.common.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;
/*
* FileName: CorsConfig.java
* Description: // 跨域配置
* Author: woolflighthouse@163.com
* Date: 2022/2/8 21:03
*/
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // * 表示对所有的地址都可以访问
corsConfiguration.addAllowedHeader("*"); // 跨域的请求头
corsConfiguration.addAllowedMethod("*"); // 跨域的请求方法
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
2.3.8 封装返回数据结果
对于前端请求的响应,会返回状态、信息和数据,对这些返回的数据进行封装,封装为一个返回数据的结果类Result。
在com.solo.common.utils下创建一个Result.java类,代码如下:
package com.solo.common.utils;
import java.io.Serializable;
/*
* FileName: Result.java
* Description: // 返回数据集封装
* Author: woolflighthouse@163.com
* Date: 2022/2/8 20:58
*/
public class Result implements Serializable {
private static final long serialVersionUID = 1L;
//
/**
* 响应码或状态码
*/
private Integer code;
/**
* 信息
*/
private String message;
/**
* 返回数据
*/
private Object data;
public Result(Integer code) {
this.code = code;
}
public Result(Integer code, String message, Object data) {
this.code = code;
this.message = message;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
2.3.9 创建登录控制器
控制器简单地说就是用于处理请求的类。基于Web的编程,其核心就是HTTP协议的请求/响应模型,这种请求/响应模型贯穿于编程的始终,前端发送来请求,后端接受请求,并作出响应,控制器就是做这个事情的。
为了完成Vue登录前端发送请求的响应,需要一个登录控制器来处理这个请求。
在com.solo.base.rbac包下创建一个存放控制器的子包,并在该子包下创建一个登录控制器LoginController.java,代码如下:
package com.solo.base.rbac.controller;
import com.solo.base.security.LoginDTO;
import com.solo.common.utils.Result;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/*
* FileName: LoginController.java
* Description: // 登录控制器
* Author: woolflighthouse@163.com
* Date: 2022/2/8 21:06
*/
@RestController
public class LoginController {
@RequestMapping(value = "/login", method = RequestMethod.POST)
public Result login(@RequestBody LoginDTO loginDTO) {
String username = loginDTO.getUsername();
String password = loginDTO.getPassword();
if (username.equals("admin") && password.equals("123456")) {
return new Result(200);
} else {
return new Result(400);
}
}
}
第16行:@RestController是一个由Spring 4.0引入的更加便捷的注解,等效于@Controller + @ResponseBody。在LoginController类上面加上@RestController,一方面表示这是一个controller类;另一方面还具有@Responsebody注解的作用。@Responsebody注解的作用是将控制器中方法返回的对象转换为指定的格式之后,写入到response对象的body区,通常用来返回json等数据,简单地说使用此注解之后返回的不是视图,而是数据。因为前后端分离不会直接返回视图,而是返回数据,比如json格式的数据,所以使用@RestController进行注解。
第18行:@RequestMapping是一个用来处理请求地址映射的注解。
第19~27行:定义了一个登录login()方法。返回值是一个Result类,参数是一个loginDTO对象,使用@RequestBody进行注解,表示以loginDTO对象接收前端传过来的json数据。
2.3.10 运行前后端程序
在终端运行前端程序,运行命令和信息如下:
Microsoft Windows [版本 10.0.19043.1466]
(c) Microsoft Corporation。保留所有权利。
D:\vue-project\lighthouse\lighthouse-vue>npm run serve
> lighthouse-vue@0.1.0 serve D:\vue-project\lighthouse\lighthouse-vue
> vue-cli-service serve
INFO Starting development server...
98% after emitting CopyPlugin
DONE Compiled successfully in 2163ms 下午8:53:29
App running at:
- Local: http://localhost:8080/
- Network: http://192.168.0.102:8080/
Note that the development build is not optimized.
To create a production build, run npm run build.
在浏览器中输入http://localhost:8080/地址,打开如图10所示的登录界面。
图10
运行后端程序如图9所示。在图10中输入账号:admin,密码:123456,登录验证成功,打开如图11所示的界面。
显示的页面表示登录成功。
至此,完成了Vue登录第2.1版。
君问归期未有期,巴山夜雨涨秋池。