SpringBoot+Vue-admin-template 实现跨域数据查询
前言
本文的案例是基于Vue-admin-template项目改造的简化版Vue后台管理模板案例
在前两篇的实案例之上,记录一下实现登录、退出、查询数据、以及跨域访问资源
的一些细节,方便自己日后忘了快速捡起,同时也是对之前两篇vue实践文章总结
技术栈
技术栈还是沿用SpringBoot+Vue-admin-template 实现增删改查中技术,版本也一致
案例演示
案例实践
1.完全按照前端的定义好的请求格式实现登录和退出接口
1.1 保持根目录下.env.development的基础API路径不变
# base api
VUE_APP_BASE_API = \'/dev-api\'
1.2 设置根目录下vue.config.js的代理到后端服务8080端口
devServer: {
port: port,
open: false,
overlay: {
warnings: false,
errors: true
},
// before: require(\'./mock/mock-server.js\') 注释mock-server生成的模拟数据
proxy: {
\'/dev-api\': {
target: `http://localhost:8080`, // 后台服务地址
changeOrigin: true,
pathRewrite: {
\'^/dev-api\': \'/dev-api\' // 路径重写
}
}
}
},
1.3 保持src\\api\\user.js的登录、获取用户信息、退出的接口不变
export function login(data) {
return request({
url: \'/vue-admin-template/user/login\',
method: \'post\',
data
})
}
export function getInfo(token) {
return request({
url: \'/vue-admin-template/user/info\',
method: \'get\',
params: { token }
})
}
export function logout() {
return request({
url: \'/vue-admin-template/user/logout\',
method: \'post\'
})
}
2.前端mock模拟生成的数据细节
2.1 login登录接口和info接口详细的数据封装
// 定义tokens对象存放token 在对象中模拟admin和editor两个角色的token
const tokens = {
admin: {
token: \'admin-token\'
},
editor: {
token: \'editor-token\'
}
}
// 分别以admin和editor两个角色的token值作为key,然后返回的数据封装成一个整体对象存放进value
const users = {
\'admin-token\': {
roles: [\'admin\'],
introduction: \'I am a super administrator\',
avatar: \'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif\',
name: \'Super Admin\'
},
\'editor-token\': {
roles: [\'editor\'],
introduction: \'I am an editor\',
avatar: \'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif\',
name: \'Normal Editor\'
}
}
// 模块化导出登录接口(可以理解为向外暴露,方便JS识别)
export default [
// user login
{
url: \'/vue-admin-template/user/login\',
type: \'post\',
// ES6箭头函数
response: config => {
const { username } = config.body // 从body中取出username
const token = tokens[username] //根据username在tokens中获取对应token
// mock error 当不是admin或者editor账号登录时,就会获取不到token报错 产生mock error
if (!token) {
return {
code: 60204,
message: \'Account and password are incorrect.\'
}
}
// 成功就会返回code为20000,data是返回数据的key值,token是一个value值的对象
return {
code: 20000,
data: token
}
}
},
// get user info 获取用户信息
{
url: \'/vue-admin-template/user/info\\.*\',
type: \'get\',
response: config => {
const { token } = config.query // 从config中取出token
const info = users[token] // 根据token从用户中取出对应用户信息
// mock error
if (!info) {
return {
code: 50008,
message: \'Login failed, unable to get user details.\'
}
}
return {
code: 20000,
data: info // 返回用户信息
}
}
},
// user logout 用户退出
{
url: \'/vue-admin-template/user/logout\',
type: \'post\',
response: _ => {
return { // 无请求内容直接返回 success和20000
code: 20000,
data: \'success\'
}
}
}
]
2.2 login登录接口返回的数据格式具体表现形式
{
"code": 20000,
"data": {
"token": "admin-token"
}
}
2.3 info接口返回的数据格式具体表现形式
{
"code":20000,
"data":{
"roles":["admin"],
"introduction":"I am a super administrator",
"avatar":"https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif",
"name":"Super Admin"
}
}
2.4 logout接口返回的数据格式具体表现形式
{
"code":20000,
"data":"success"
}
3.用SpringBoot编写与mock.js同样的数据返回
3.1 User.java实体类
@Data
public class User {
private List<String> roles;
private String introduction;
private String avatar;
private String name;
private String username;
private String password;
}
3.2 LoginController.java控制器类
@Controller
public class LoginController {
@CrossOrigin
@PostMapping(value = "/vue-admin-template/user/login")
@ResponseBody
public Map login(@RequestBody User user) {
String username = user.getUsername();
HashMap<String, Object> tokens = new HashMap<>();
tokens.put("admin","admin-token");
tokens.put("editor","editor-token");
HashMap<String, Object> response = new HashMap<>();
HashMap<String, Object> responseData = new HashMap<>();
responseData.put("token",tokens.get(username));
response.put("code",20000);
response.put("msg","登录成功");
response.put("data",responseData);
return response;
}
@CrossOrigin
@GetMapping(value = "/vue-admin-template/user/info")
@ResponseBody
public Map info(@RequestParam("token")String token) {
HashMap<String, Object> users = new HashMap<>();
User adminUser = new User();
User editorUser = new User();
List<String> adminRole = new ArrayList<String>();
adminRole.add("admin-token");
List<String> editorRole = new ArrayList<String>();
adminRole.add("editor-token");
adminUser.setRoles(adminRole);
adminUser.setIntroduction("I am a super administrator");
adminUser.setAvatar("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
adminUser.setName("Super Admin");
editorUser.setRoles(editorRole);
editorUser.setIntroduction("I am an editor");
editorUser.setAvatar("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
editorUser.setName("Normal Editor");
users.put("admin-token",adminUser);
users.put("editor-token",editorUser);
HashMap<String, Object> responseData = new HashMap<>();
responseData.put("code",20000);
responseData.put("msg","登录成功");
responseData.put("data",users.get(token));
return responseData;
}
@CrossOrigin
@PostMapping(value = "/vue-admin-template/user/logout")
@ResponseBody
public Map logout() {
HashMap<String, Object> responseData = new HashMap<>();
responseData.put("code",20000);
responseData.put("msg","退出成功");
responseData.put("data","success");
return responseData;
}
}
4.同源策略以及跨域访问资源
4.1同源策略
同源策略是一种保证浏览器网络较为安全的策略模式和功能,同源策略最早出现在网景公司旗下的网景浏览器上
什么是同源
源:由协议,域名,端口三者组成,
同源:指协议,域名,端口这三者相同
同源策略: 浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源
举个例子:
http://localhost:9528下的脚本在没有明确授权的情况下,是不能读写http://localhost:8080下的资源
什么是跨域
浏览器在遵守同源策略模式下,不是同源的脚本不能操作其他源下面的对象。
想要操作另一个源下的对象是就需要跨域。
举例:
http://localhost:9528下的脚本想要访问http://localhost:8080下的JSON数据或者CSS,IMAGES等静态资源,需要进行跨域操作,这种操作称为跨域访问资源(跨域读和写资源)
4.2跨域解决方案(跨域的实现方式)
1.JSONP方式
首先必须要知道的是带有"src"这个属性的标签都拥有跨域的能力,比如