-
Notifications
You must be signed in to change notification settings - Fork 649
JSONP
JoyChou edited this page Jul 3, 2019
·
8 revisions
代码很简单:
@ControllerAdvice
public class JSONPAdvice extends AbstractJsonpResponseBodyAdvice {
public JSONPAdvice() {
super("callback", "cback"); // callback的参数名,可以为多个
}
}
当有接口返回了Object(比如JSONObject或者JavaBean,但是不支持String),只要在参数中加入callback=test
或cback=test
就会自动变成JSONP接口。比如下面代码:
@RequestMapping(value = "/advice", produces = MediaType.APPLICATION_JSON_VALUE)
public JSONObject advice() {
String info = "{\"name\": \"JoyChou\", \"phone\": \"18200001111\"}";
return JSON.parseObject(info);
}
虽然上面代码指定了response的content-type
为application/json
,但是在AbstractJsonpResponseBodyAdvice
类中会设置为application/javascript
,提供给前端调用。
设置content-type
为application/javascript
的代码:
protected MediaType getContentType(MediaType contentType, ServerHttpRequest request, ServerHttpResponse response) {
return new MediaType("application", "javascript");
}
并且还会判断callback的参数只是否是有效的,代码如下:
private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\\.]*");
protected boolean isValidJsonpQueryParam(String value) {
return CALLBACK_PARAM_PATTERN.matcher(value).matches();
}
返回:
/**/test({"phone":"18200001111","name":"JoyChou"});
使用jax的jsonp调用方式,运行后会弹框JoyChou
。
<html>
<head>
<meta charset="UTF-8" />
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<script language="JavaScript">
$(document).ready(function() {
$.ajax({
url:'http://localhost:8080/jsonp/advice',
dataType:'jsonp',
success:function(data){
alert(data.name)
}
});
});
</script>
</body>
</html>
有时候开发同学为了测试方便,JSONP接口能直接访问,不直接访问做了Referer限制。正常来讲,前端发起的请求默认都会带着Referer,所以简单说下如何绕过空Referer。
<html>
<meta name="referrer" content="no-referrer" />
<script>
function test(data){
alert(data.name);
}
</script>
<script src=http://localhost:8080/jsonp/emptyReferer?callback=test></script>
</html>
<iframe src="javascript:'<script>function test(data){alert(data.name);}</script><script src=http://localhost:8080/jsonp/emptyReferer?callback=test></script>'"></iframe>