1.前端解决(9种)
同源策略
-
跨域:浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。
-
同源策略:如果两个页面的协议,域名,端口都相同,则两个页面具有相同的源。
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。这是一个用于隔离潜在恶意文件的重要安全机制。
不受同源策略限制的
-
页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
-
跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的
<script src="..."></script>,<img>,<link>,<iframe>
等。
受到限制的
-
Cookie、LocalStorage 和 IndexDB 无法读取
-
DOM和JS对象无法获得
-
AJAX 请求不能发送
跨域解决方案
一、JSONP跨域
-
jsonp的核心原理就是:目标页面回调本地页面的方法,并带入参数
-
服务器端实现 JSONP 接口的步骤
-
服务器端获取客户端发送过来的query参数,其中参数有回调函数的名字
-
得到的数据,拼接出一个函数调用的字符串
-
把上一步拼接得到的字符串,响应给客户端的
<script>
标签进行解析执行
-
-
jsonp的缺点:只能发送get一种请求。
1、原生JS实现
通过script标签src属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据。
<script>
function getData(data){
console.log(data)
}
</script>
<script src="http://127.0.0.1:3000/web?cb=getData"></script>
后端nodejs代码
主要用来模拟服务器
携带参数必须是字符串
const express=require('express')
const router=express.Router()
router.get('/web',(req,res)=>{
let {cb}=req.query
console.log(req.query)
var data = {
name: 'xtt',
age: 18,
gender:'女孩子'
}
// 携带参数必须是字符串
res.send(`${cb}(${JSON.stringify(data)})`)
router.get('/que',(req,res)=>{
res.send(`${req.query.cb}('dd')`)
})
})
module.exports=router
2、jquery Ajax实现
以jquery来发起jsonp请求
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.10.0/jquery.js"></script>
<script>
let url = 'http://127.0.0.1:3000/que?cb=getData'
$.ajax({
method: 'GET',
url,
dataType: 'jsonp',
success: (res) => {
console.log(res)
}
})
</script>
3、Vue axios实现
handleCallback({"success": true, "user": "admin"})
this.$http = axios;
this.$http.jsonp('http://127.0.0.1:3000/que?cb=getData', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
二、跨域资源共享(CORS)
-
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
-
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
-
CORS需要浏览器和服务器同时支持。
-
目前,所有主流浏览器都支持该功能,IE10以下不支持。
-
浏览器将CORS跨域请求分为:简单请求、非简单请求。
-
简单请求与非简单请求
简单请求
浏览器在发送跨域请求的时候,会先判断下是简单请求还是非简单请求,如果是简单请求,就先执行服务端程序,然后浏览器才会判断是否跨域。
同时满足以下的两个条件,就属于简单请求。浏览器对这两种的处理,是不一样的。
-
请求方式:get/post/head其中一种
-
请求头设置:
-
Accept
-
Accept-Language
-
Content-Type:application/x-www-form-urlencoded、multipart/form-data、text/plain( 只限于三个值中的一个)
-
详细描述
对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。
举例:
-
发起请求
-
自动在头信息之中,添加一个Origin字段。
GET /cors HTTP/1.1 Origin: http://127.0.0.1:8080 Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
Origin:本次请求来自哪个域(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
-
服务器判断此次请求Origin源
-
有三个与 CORS 请求相关的字段,都以Access-Control-开头。
Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8
-
浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被请求的异常回调函数捕获。
注意,这种错误无法通过状态码识别,因为 HTTP 回应的状态码有可能是200。
-
不在许可范围内:服务器会返回一个正常的 HTTP 回应。
-
在许可范围内:服务器返回的响应,会多出几个头信息字段。
-
-
Access-Control解释
-
Access-Control-Allow-Origin:必须的
它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
-
Access-Control-Allow-Credentials:可选
布尔值,表示是否允许发送 Cookie。默认情况下,Cookie 不包括在 CORS 请求之中(为了降低 CSRF 攻击的风险。)。设为true,即表示服务器明确许可,浏览器可以把 Cookie 包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送 Cookie,不发送该字段即可。
-
Access-Control-Expose-Headers:可选
CORS 请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个服务器返回的基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值。
-
非简单请求
对服务器提出特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
预检请求
-
非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为“预检”请求(preflight)。
-
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 方法和头信息字段。
-
只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
-
这是为了防止这些新增的请求,对传统的没有 CORS 支持的服务器形成压力,给服务器一个提前拒绝的机会,这样可以防止服务器收到大量DELETE和PUT请求,这些传统的表单不可能跨域发出的请求
举例
两个特殊字段:
服务器收到“预检”请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应
-
自动发出一个“预检”请求,要求服务器确认可以这样请求。下面是这个“预检”请求的 HTTP 头信息:
OPTIONS /cors HTTP/1.1 Origin: http://api.bob.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Custom-Header Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
-
Access-Control-Request-Method必须的
用来列出浏览器的 CORS 请求会用到哪些 HTTP 方法,上例是PUT。
-
Access-Control-Request-Headers
该字段是一个逗号分隔的字符串,指定浏览器 CORS 请求会额外发送的头信息字段。
-
-
预检请求的回应:
服务器收到"预检"请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。
HTTP回应中,除了关键的是Access-Control-Allow-Origin字段,其他CORS相关字段如下:
-
Access-Control-Allow-Methods:必选
它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。
-
Access-Control-Allow-Headers
如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。
-
Access-Control-Allow-Credentials:可选
该字段与简单请求时的含义相同。
-
Access-Control-Max-Age:可选
用来指定本次预检请求的有效期,单位为秒。
CORS跨域
1)前端设置
let xhr;
try {
xhr=new XMLHttpRequest();
} catch (error) {
xhr=new ActiveXObject('Microsoft.XMLHTTP');
}
xhr.open('post','http://localhost:3000/login',true);
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
xhr.send('name=111&age=12');
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
let reg=/^2\d{2}/
if(reg.test(xhr.status)){
console.log(JSON.parse(xhr.response))
}
}
}
nodejs代码
在Express中通过第3方中间件来完成cors跨域解决
使用步骤分为如下 3 步:
-
运行 npm install cors 安装中间件
-
使用 const cors = require('cors') 导入中间件
-
在路由之前调用 app.use(cors()) 配置中间件
const express=require('express')
const cors=require('cors')
const app=express()
app.listen(3000)
const allowHosts=[
'http://localhost:5000',
'http://localhost:2000'
]
app.use(cors())
app.use((req,res,next)=>{
let hst =req.header.origin
if(allowHosts.includes(hst)){
next()
}else{
return res.send({
code:404,
msg:'地址不对'
})
}
})
app.get('/login',(req,res)=>{
res.send('登陆')
})
三、Nginx 反向代理解决跨域问题
CSDN地址:使用nginx解决跨域问题_空城1995的博客-CSDN博客_nginx怎么解决跨域问题
Nginx教程地址:nginx.conf配置文件解析(http、server、location) - 灰信网(软件开发博客聚合)
正向代理和反向代理
提到代理,肯定要说一下这两个的区别。
-
举个正向代理的例子
我打球累了走不动了,找看球的小朋友帮我去旁边的商店买瓶水。商店老板是不知道到底是谁需要喝水的,隐藏了客户端。当然,小朋友可以告诉老板就是那个打球像蔡徐坤的人要喝水。还有,VPN 就是正向代理。
-
反向代理的例子
我打球累了,找看球的小朋友要瓶水喝(当然我肯定会给钱的:D)。我不需要知道小朋友的水是从旁边的商店还是两公里外的超市买的。隐藏了服务端。还有,我们连好了 VPN 访问谷歌的时候,浏览的那些页面,我们是不会知道具体是哪台服务器的资源。
nginx配置解决iconfont跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。
location / {
add_header Access-Control-Allow-Origin *;
}
nginx反向代理接口跨域
跨域问题:同源策略仅是针对浏览器的安全策略。服务器端调用HTTP接口只是使用HTTP协议,不需要同源策略,也就不存在跨域问题。
实现思路:通过Nginx配置一个代理服务器域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域访问。
nginx具体配置
#proxy服务器
server {
listen 81;
server_name www.domain1.com;
location / {
proxy_pass http://www.yp2.com:8080; #反向代理
proxy_cookie_domain www.yp2.com www.yp1.com; #修改cookie里域名
index index.html index.htm;
# 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
add_header Access-Control-Allow-Origin http://www.yp1.com; #当前端只跨域不带cookie时,可为*
add_header Access-Control-Allow-Credentials true;
}
}
四、nodejs中间件代理跨域
node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。
1、nodejs服务器代理
使用node + express + http-proxy-middleware搭建一个proxy服务器。
npm i express htttp-proxy-middleware
const express=require('express')
const app=express()
app.listen(5000)
const httpProxyMiddleware=require('http-proxy-middleware')
// 服务器代理 ---接口中间层 代理层
app.use('/api' ,httpProxyMiddleware.createProxyMiddleware({
// 代理的地址
target:'http://localhost:8989',
// 默认false不修改。修改代理请求是他的主机名
changeOrigin:true,
// 修改响应头信息,实现跨域并允许带cookie
onProxyRes: function(proxyRes, req, res) {
res.header('Access-Control-Allow-Origin', 'http://localhost:5000');
res.header('Access-Control-Allow-Credentials', 'true');
},
// 匹配规则
pathRewrite:{
// 访问路径 映射到 目标服务器中的路径
'^/v1/api':'/'
}
}))
2、vue框架的跨域
vue中实现开发环境的时的反向代理进行跨域解决,在项目根目录下面创建一个vue.config.js文件,写下如下代码
vue.config.js部分配置:
module.exports={
// 指定服务器模块
devServer:{
// 代理
proxy:{
'/v1/api':{
// 目标地址
target:'http://localhost:3000',
changeOrigin:true,
pathRewrite:{
'/v1/api':'/api'
}
}
}
}
}
五、document.domain + iframe跨域
前提条件
这两个域名必须属于同一个一级域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域。
Javascript出于对安全性的考虑,而禁止两个或者多个不同域的页面进行互相操作。
而相同域的页面在相互操作的时候不会有任何问题。
alert(document.domain = "baidu.com"); //"baidu.com"
alert(document.domain = "www.baidu.com"); //"www.baidu.com"
举例
1)父窗口:(http://father.baidu.com/a.html)
<iframe id="iframe" src="http://child.baidu.com/b.html"></iframe>
<script>
document.domain = 'baidu.com';
var user = 'admin';
</script>
预览
1)子窗口:(http://child.baidu.com/b.html)
<script>
document.domain = 'baidu.com';
// 获取父窗口中变量
console.log('get js data from parent ---> ' + window.parent.user);
</script>
六、location.hash + iframe跨域
hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)。
实现原理
-
a想要与b跨域相互通信,通过中间页c来实现。
-
三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
-
利用location.hash传值,创建定时器,坚持hash的变化,执行相应的操作。
下面我们来完成一个案例:
具体实现
-
A域:a.html -> B域:b.html -> A域:c.html
-
a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。
1)a.html:(http://www.baidu1.com/a.html)
<iframe id="iframe" src="http://www.baidu2.com/b.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
// 向b.html传hash值
setTimeout(function() {
iframe.src = iframe.src + '#user=admin';
}, 1000);
// 开放给同域c.html的回调方法
function onCallback(res) {
alert('data from c.html ---> ' + res);
}
</script>
2)b.html:(http://www.baidu2.com/b.html)
<iframe id="iframe" src="http://www.baidu1.com/c.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
// 监听a.html传来的hash值,再传给c.html
window.onhashchange = function () {
iframe.src = iframe.src + location.hash;
};
</script>
3)c.html:(http://www.baidu1.com/c.html)
<script>
// 监听b.html传来的hash值
window.onhashchange = function () {
// 再通过操作同域a.html的js回调,将结果传回
window.parent.parent.onCallback('hello: ' + location.hash.replace('#user=', ''));
};
</script>
优缺点
-
location.hash + iframe跨域的优点:
-
可以解决域名完全不同的跨域
-
可以实现双向通讯
-
-
location.hash + iframe跨域的缺点:
-
location.hash会直接暴露在URL里,并且在一些浏览器里会产生历史记录,数据安全性不高也影响用户体验
-
另外由于URL大小的限制,支持传递的数据量也不大。
-
七、window.name + iframe解决跨域
window.name属性的独特之处:只要在一个window下,无论url怎么变化,只要设置好了window.name,那么后续就一直都不会改变。同理,在iframe中,即使url在变化,iframe中的window.name也是一个固定的值,利用这个,我们就可以实现跨域了(2MB)。
举例
test1.html
<body>
<h2>test1页面</h2>
<iframe src="http://192.168.0.1/php_demo/test2.html" frameborder="1"></iframe>
<script>
var ifr = document.querySelector('iframe')
ifr.style.display = 'none'
var flag = 0;
ifr.onload = function () {
console.log('跨域获取数据', ifr.contentWindow.name);
ifr.contentWindow.close();
}
</script>
</body>
test2.html
<body>
<h2>test2页面</h2>
<script>
var person = {
name: '大鹏_yp',
age: 24,
school: 'lngydx'
}
window.name = JSON.stringify(person)
</script>
</body>
通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
八、postMessage通信跨域
PWA渐进式web应用
-
在HTML5中新增了postMessage方法,postMessage可以实现跨文档消息传输(Cross Document Messaging)
-
该方法可以通过绑定window的message事件来监听发送跨文档消息传输内容。
-
它可用于解决以下方面的问题:
a. 页面和其打开的新窗口的数据传递
b. 多窗口之间消息传递
c. 页面与嵌套的iframe消息传递
d. 上面三个场景的跨域数据传递 -
postMessage用法:
postMessage(data,origin)方法接受两个参数
参数说明:
-
data:html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
-
origin:协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
-
举例
-
postMessage:发送
-
onmessage:接收
1)a.html:(http://www.baidu1.com/a.html)
<iframe id="iframe" src="http://www.baidu2.com/b.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
iframe.onload = function() {
var data = {
name: 'aym'
};
// 向domain2传送跨域数据
iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.baidu2.com');
};
// 接受baidu2返回数据
window.addEventListener('message', function(e) {
alert('data from baidu2 ---> ' + e.data);
}, false);
</script>
2)b.html:(http://www.baidu2.com/b.html)
<script>
// 接收baidu1的数据
window.addEventListener('message', function(e) {
alert('data from baidu1 ---> ' + e.data);
var data = JSON.parse(e.data);
if (data) {
data.number = 16;
// 处理后再发回baidu1
window.parent.postMessage(JSON.stringify(data), 'http://www.baidu1.com');
}
}, false);
</script>
九、WebSocket协议跨域
-
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
-
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
WebSocket 如何工作
Web浏览器和服务器都必须实现 WebSockets 协议来建立和维护连接。由于 WebSockets 连接长期存在,与典型的HTTP连接不同,对服务器有重要的影响。
基于多线程或多进程的服务器无法适用于 WebSockets,因为它旨在打开连接,尽可能快地处理请求,然后关闭连接。任何实际的 WebSockets 服务器端实现都需要一个异步服务器。
案例
1)前端代码:
<div>user input:<input type="text"></div>
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
<script>
var socket = io('http://www.baidu2.com:8080');
// 连接成功处理
socket.on('connect', function() {
// 监听服务端消息
socket.on('message', function(msg) {
console.log('data from server: ---> ' + msg);
});
// 监听服务端关闭
socket.on('disconnect', function() {
console.log('Server socket has closed.');
});
});
document.getElementsByTagName('input')[0].onblur = function() {
socket.send(this.value);
};
</script>
2)Nodejs socket后台:
var http = require('http');
var socket = require('socket.io');
// 启http服务
var server = http.createServer(function(req, res) {
res.writeHead(200, {
'Content-type': 'text/html'
});
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');
// 监听socket连接
socket.listen(server).on('connection', function(client) {
// 接收信息
client.on('message', function(msg) {
client.send('hello:' + msg);
console.log('data from client: ---> ' + msg);
});
// 断开处理
client.on('disconnect', function() {
console.log('Client socket has closed.');
});
});
作者 | 久宇诗
来源 | cnblogs.com/ypSharing/p/corsHanlder.html
2.后端解决(4种)
方法一:实现 WebMvcConfigurer接口
实现 WebMvcConfigurer#addCorsMappings 的方法
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
方法二:重新注入 CorsFilter
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 CorsFilterConfig {
/**
* 开启跨域访问拦截器
*
* @date 2021/4/29 9:50
*/
@Bean
public CorsFilter corsFilter() {
//创建CorsConfiguration对象后添加配置
CorsConfiguration corsConfiguration = new CorsConfiguration();
//设置放行哪些原始域
corsConfiguration.addAllowedOrigin("*");
//放行哪些原始请求头部信息
corsConfiguration.addAllowedHeader("*");
//放行哪些请求方式
corsConfiguration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//2. 添加映射路径
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(source);
}
}
方法三:创建一个 filter 解决跨域
@Slf4j
@Component
@WebFilter(urlPatterns = { "/*" }, filterName = "headerFilter")
public class HeaderFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
//解决跨域访问报错
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
//设置过期时间
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization");
// 支持HTTP 1.1.
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
// 支持HTTP 1.0. response.setHeader("Expires", "0");
response.setHeader("Pragma", "no-cache");
// 编码
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, resp);
}
@Override
public void init(FilterConfig filterConfig) {
log.info("跨域过滤器启动");
}
@Override
public void destroy() {
log.info("跨域过滤器销毁");
}
}
方法四:使用 CrossOrigin 注解
可以使用在单个方法上也可以使用在类上
Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ORIGINS = {"*"};
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ALLOWED_HEADERS = {"*"};
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
boolean DEFAULT_ALLOW_CREDENTIALS = false;
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
long DEFAULT_MAX_AGE = 1800;
/**
* Alias for {@link #origins}.
*/
@AliasFor("origins")
String[] value() default {};
/**
* A list of origins for which cross-origin requests are allowed. Please,
* see {@link CorsConfiguration#setAllowedOrigins(List)} for details.
* <p>By default all origins are allowed unless {@code originPatterns} is
* also set in which case {@code originPatterns} is used instead.
*/
@AliasFor("value")
String[] origins() default {};
/**
* Alternative to {@link #origins()} that supports origins declared via
* wildcard patterns. Please, see
* @link CorsConfiguration#setAllowedOriginPatterns(List)} for details.
* <p>By default this is not set.
* @since 5.3
*/
String[] originPatterns() default {};
/**
* The list of request headers that are permitted in actual requests,
* possibly {@code "*"} to allow all headers.
* <p>Allowed headers are listed in the {@code Access-Control-Allow-Headers}
* response header of preflight requests.
* <p>A header name is not required to be listed if it is one of:
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
* {@code Last-Modified}, or {@code Pragma} as per the CORS spec.
* <p>By default all requested headers are allowed.
*/
String[] allowedHeaders() default {};
/**
* The List of response headers that the user-agent will allow the client
* to access on an actual response, other than "simple" headers, i.e.
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
* {@code Expires}, {@code Last-Modified}, or {@code Pragma},
* <p>Exposed headers are listed in the {@code Access-Control-Expose-Headers}
* response header of actual CORS requests.
* <p>The special value {@code "*"} allows all headers to be exposed for
* non-credentialed requests.
* <p>By default no headers are listed as exposed.
*/
String[] exposedHeaders() default {};
/**
* The list of supported HTTP request methods.
* <p>By default the supported methods are the same as the ones to which a
* controller method is mapped.
*/
RequestMethod[] methods() default {};
/**
* Whether the browser should send credentials, such as cookies along with
* cross domain requests, to the annotated endpoint. The configured value is
* set on the {@code Access-Control-Allow-Credentials} response header of
* preflight requests.
* <p><strong>NOTE:</strong> Be aware that this option establishes a high
* level of trust with the configured domains and also increases the surface
* attack of the web application by exposing sensitive user-specific
* information such as cookies and CSRF tokens.
* <p>By default this is not set in which case the
* {@code Access-Control-Allow-Credentials} header is also not set and
* credentials are therefore not allowed.
*/
String allowCredentials() default "";
/**
* The maximum age (in seconds) of the cache duration for preflight responses.
* <p>This property controls the value of the {@code Access-Control-Max-Age}
* response header of preflight requests.
* <p>Setting this to a reasonable value can reduce the number of preflight
* request/response interactions required by the browser.
* A negative value means <em>undefined</em>.
* <p>By default this is set to {@code 1800} seconds (30 minutes).
*/
long maxAge() default -1;
3.其他
1.vue.config.js
module.exports = {
// webpack-dev-server 相关配置
devServer: {
proxy: {
'/api': {
target: 'http://localhost:9212/', //接口域名
changeOrigin: true, //是否跨域
ws: true, //是否代理 websockets
secure: true, //是否https接口
pathRewrite: { //路径重置
'^/api': ''
}
}
}
}
}
2.request.js
const request = axios.create({
baseURL:'/api',
timeout: 30000,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
})
3.js
//通过参数获取水库数量
export function getSticsRsvrNumByParam(query) {
return request({
url: '/bigscreen/home/getSticsRsvrNumByParam',
method: 'get',
params: query
})
}
4.后端
/**
* @description: 首页Controller
* @create: 2022-03-15 13:28
*/
@Api(value = "首页接口库",tags = "首页接口")
@RestController
@RequestMapping("/bigscreen/home")
public class HomeController {
@Autowired
private IMoitroWarnService iMoitroWarnService;
/**
* 根据行政区划、规模、等别统计水库数量
*/
@ApiOperation(value = "根据行政区划、规模、等别统计水库数量",notes = "根据行政区划、规模、等别统计水库数量")
@GetMapping("/getSticsRsvrNumByParam")
public AjaxResult getSticsRsvrNumByParam(QueryParam param){
JSONObject obj = iMoitroWarnService.getSticsRsvrNumByParam(param);
return AjaxResult.success(obj);
}
}