WebAPI的跨域访问CORS三种方法

时间:2023-03-09 17:35:32
WebAPI的跨域访问CORS三种方法

跨域访问:

JSONP的原理利用<script>没有跨域访问的限制,利用<script>的src跨域访问api,api会根据数据把json包装在一个js里面,这样跨域的客户端拿到json的包装(json padding)就会调用本地的函数解析数据。总结来说就是利用两点1、浏览器的跨域限制其实是接收了数据,但限制使用跨域数据。2是利用script标签可以跨域回调的功能

1、JSONP——js

api服务端

public HttpResponseMessage GetAllContacts(string callback)
{
Contact[] contacts = new Contact[]
{
new Contact{ Name="张三", PhoneNo="", EmailAddress="zhangsan@gmail.com"},
new Contact{ Name="李四", PhoneNo="", EmailAddress="lisi@gmail.com"},
new Contact{ Name="王五", PhoneNo="", EmailAddress="wangwu@gmail.com"},
};
JavaScriptSerializer serializer = new JavaScriptSerializer();
string content = string.Format("{0}({1})", callback, serializer.Serialize(contacts));
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(content, Encoding.UTF8, "text/javascript")
};
}

客户端

<head>
<title>联系人列表</title>
<script type="text/javascript" src="@Url.Content("~/scripts/jquery-1.10.2.js")"></script>
<script type="text/javascript">
function listContacts(contacts)
{
$.each(contacts, function (index, contact) {
var html = "<li><ul>";
html += "<li>Name: " + contact.Name + "</li>";
html += "<li>Phone No:" + contact.PhoneNo + "</li>";
html += "<li>Email Address: " + contact.EmailAddress + "</li>";
html += "</ul>";
$("#contacts").append($(html));
});
}
</script>
</head>
<body>
<ul id="contacts"></ul>
<script type="text/javascript" src="http://localhost:3721/api/contacts?callback=listContacts"></script>
</body>
</html>

2、JSONP——JsonMediaTypeFormatter

服务端定义类:

    public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter
{
public string Callback { get; private set; }
public JsonpMediaTypeFormatter(string callback = null)
{
this.Callback = callback;
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
if (string.IsNullOrEmpty(this.Callback))
{
return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
}
try
{
this.WriteToStream(type, value, writeStream, content);
return Task.FromResult<AsyncVoid>(new AsyncVoid());
}
catch (Exception exception)
{
TaskCompletionSource<AsyncVoid> source = new TaskCompletionSource<AsyncVoid>();
source.SetException(exception);
return source.Task;
}
} private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
JsonSerializer serializer = JsonSerializer.Create(this.SerializerSettings);
using (StreamWriter streamWriter = new StreamWriter(writeStream, this.SupportedEncodings.First()))
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter) { CloseOutput = false })
{
jsonTextWriter.WriteRaw(this.Callback + "(");
serializer.Serialize(jsonTextWriter, value);
jsonTextWriter.WriteRaw(")");
}
} public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
if (request.Method != HttpMethod.Get)
{
return this;
}
string callback;
if (request.GetQueryNameValuePairs().ToDictionary(pair => pair.Key, pair => pair.Value).TryGetValue("callback", out callback))
{
return new JsonpMediaTypeFormatter(callback);
}
return this;
} [StructLayout(LayoutKind.Sequential, Size = )]
private struct AsyncVoid{ }
}

注册到Global中

GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter());

直接返回数据让系统自动协商优先使用

客户端:

$(function ()
{
$.ajax({
type: "GET",
url: "http://localhost:3721/api/contacts",
dataType: "jsonp",
success: listContacts
});
}); function listContacts(contacts) {
$.each(contacts, function (index, contact) {
var html = "<li><ul>";
html += "<li>Name: " + contact.Name + "</li>";
html += "<li>Phone No:" + contact.PhoneNo + "</li>";
html += "<li>Email Address: " + contact.EmailAddress
+ "</li>";
html += "</ul>";
$("#contacts").append($(html));
});
}

3、Microsoft AsRNET Web API2Cross-Origin support

原理:利用http的响应包标识Header;Access-Control-Allow-Origin等等标签标识允许跨域访问

Install-Package Microsoft.AspNet.WebApi.Cors

开启方法:

GlobalConfiguration.Configuration.EnableCors();

或在webapiconfig注册路由里开启

config.EnableCors();

api使用特性:

[EnableCors("http://localhost:9527","*","*")]

做全局配置Global/WebApiConfig:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("www.clientA.com", "*", "*");
config.EnableCors(cors);
// ...
}
}

也可以只针对Controller或者Action做配置

[EnableCors(origins: "http://www.ClientA.com", headers: "*", methods: "*")]
public class ItemsController : ApiController
{
public HttpResponseMessage GetAll() { ... }
[EnableCors(origins: "http://www.ClientB.com", headers: "*", methods: "*")]
public HttpResponseMessage GetItem(int id) { ... }
public HttpResponseMessage Post() { ... } [DisableCors]
public HttpResponseMessage PutItem(int id) { ... }
}