挑戰常規--為什麼不應該使用Jsonp進行跨域
常規跨域的方法
常見跨域的方法有:
- 新增Access-Control-Allow-Origin
- 後臺伺服器代理
- Jsonp
1、2兩種方法都是安全可靠的,3是不安全不可靠的
Json的本質
Json本質是引用並執行外部JavaScript指令碼 ,原理是<scrpit>標籤不受域名的限制,通過動態建立<scrpit>來執行js函式
Jsonp的使用
jQuery執行Jsonp使用
$.ajax(url,{ dataType:"jsonp", error:function(jqXHR,textStatus,errorThrown) { //TODO }, success:function(data) { //TODO } });
jQuery3.3.1載入執行外部js
function DOMEval( code, doc, node ) { doc = doc || document; var i, script = doc.createElement( "script" ); script.text = code; if ( node ) { for ( i in preservedScriptAttributes ) { if ( node[ i ] ) { script[ i ] = node[ i ]; } } } doc.head.appendChild( script ).parentNode.removeChild( script ); }
不安全
使用者輸入不可信,外部指令碼同樣不可信。若A網站引用了B網站的跨域指令碼,那麼A網站的安全受B網站牽制。
安全情況下,safeapi.php
<?php date_default_timezone_set('asia/shanghai'); $result=json_encode(array("msg"=>"你好,當前時間:".date("Y-m-d H:i:s e"))); if(isset($_REQUEST['callback'])) { header("Content-Type:text/javascript;charset=utf-8"); echo $_REQUEST['callback']."(".$result.")"; }else { header("Content-Type:application/json;charset=utf-8"); echo $result; }
B網站受到攻擊或惡意程式碼,danger.php
<?php header("Content-Type:text/javascript;charset=utf-8"); if(isset($_REQUEST['callback'])) { echo $_REQUEST['callback']."("; }else { echo "_("; } echo json_encode(array("msg"=>"你好,當前時間:".date("Y-m-d H:i:s"))); echo ");console.log('do something');";
在A網站下控制檯輸出 do something
思考
應該對網站安全進行隔離,不應輕易相信外部指令碼,否則很容易造成賬號洩漏等安全風險。如果的確需要引用執行外部指令碼,可以使用CSP 策略指令進行白名單控制,如:
Content-Security-Policy: default-src 'self' trustedscripts.foo.com