关于WebService、WebApi的跨域问题
随着移动互联网的发展, 传统营销模式往网站以及移动客户端转移已经成为一种趋势。接触过互联网开发的开发者肯定会很熟悉两种网络服务WebApi、WebService。在使用JavaScript进行数据交互时会遇到一个问题,那就是JavaScript的同源策略,简单的来讲同源策略就是指一段脚本只能读取来自同一来源的窗口和文档的属性,这里的同一来源指的是主机名、协议和端口号的组合。以下是我对同源策略的理解,可能不完善:
| 请求URL | 请求结果 | 原因 |
| http://wangyu.testurl.com/WebApi/test | YES | 当前域 |
| http://wangyu.testurl.com/WebApi/test2 | YES | 当前域 |
| http://wangyu.testurl.com/WebApi2/test | NO | 跨域/端口不同 |
| http://wangyu2.testurl.com/WebApi2/test | NO | 跨域/主机不同 |
| https://wangyu.testurl.com/WebApi/test | NO | 协议不同 |
一、WebApi的跨域问题解决:
1.从客户端来解决跨域问题:
从客户端来解决跨域问题就是从调用方的解决跨域访问,需要每个客户端自己来做处理,常见的JSONP回调方式。(本文略过,本博文主要讲解从服务端解决跨域的方法)
2.从服务端来解决跨域:
(1)ASP.NET Web API对CORS提供的原生支持的实现:
ASP.NET Web API对CORS提供的原生支持实现在一个名为“Microsoft ASP.NET Web API 2 Cross-Origin Support”的NuGet包中。当我们安装这个包之后,现 有的packages目录下会添加两个名称分别为“Microsoft.AspNet.Cors”和“Microsoft.AspNet.WebApi.Cors”,针对保存其中的两个程序集(System.Web.Cors.dll和System.Web.Http.Cors.dll)的引用被自动添加到项目中。
具体操作步骤:①VS工具条“工具”->"NuGet工具管理器"->"程序包管理控制台"②在控制台输入Install-Package Microsoft.AspNet.WebApi.Cors(当然要在联网状态)此时编译器就会为我们安装对应的程序集。在安装程序集之后,跨域支持是默认关闭的,需要我们添加部分代码:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//打开跨域支持
config.EnableCors();
// Web API 配置和服务
// 将 Web API 配置为仅使用不记名令牌身份验证。
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); // Web API 路由
config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
然后在对应的控制器添加对应的属性,就可以让特定的控制器支持跨域访问。比如我自己的示例:
namespace Jiuka.Webapi.Controllers
{
/// <summary>
/// Class UserController.
/// </summary>
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class UserController : ApiController
{
/// <summary>
/// 注册用户
/// </summary>
/// <param name="model">The model.</param>
/// <returns>System.String.</returns>
[System.Web.Http.HttpPost] public string NewUser([FromBody] MUserInfo model)
{
bool res = WcfCallHelper.Instance.Invoke<bool, IUserService, MUserInfo>(model, "RegisteUser");
if(!res)
{
return "注册失败!";
}
MOperateLog temp = new MOperateLog();
temp.KeyID = model.KeyID;
temp.Operate = "注册";
temp.OpUser = model.Name;
temp.TrackID = model.KeyID;
temp.Detail = string.Format("{0}注册了账号,初始密码是:{1}", model.Name, model.Password);
LogMannager.WriteLog(temp);
return "注册成功!";
}
}
}
[EnableCors(origins: "*", headers: "*", methods: "*")]里面*号表示不加任何限定,具体的使用方法可以自己去学习。提示:当我们自定义参数类型时,要为参数加上[FromBody]属性,并且在Ajax提交的时候,不加DataType选项,要不然会出问题,亲测过!
3.从部署的服务器的配置上解决跨域限制问题:
当我们的WebApi需要跨域调用调试或者是完成了本地调试不要上服务器开始外网服务时,需要将我们写好的web服务部署在服务器上,这时候可以通过服务器上的一些配置选项来解决跨域限制问题。
具体操作方法:当我们把我们的服务部署到服务器之后打开IIS管理器,选中对应的服务,我们会看到如下一个菜单选项:

选则HTTP响应标头菜单,添加如下三个响应标头:

Access-Control-Allow-Origin 表示请求的来源,其格式:”地址:端口号”,”域名”,当其值为”*”表示不限定。标头设置好之后重新启动网站,跨域访问限制问题就解决了。
二、WebService的跨域问题解决:
1.从客户端调用来解决跨域限制:同上的,采用JSONP方式调用(掠过)。
2.从服务端解决跨域限制:①采用WebApi的同样的方法,设置我们的IIS服务器HTTP响应标头②采用ServiceStack服务框架
采用ServiceStack服务框架跨域的具体实现:
首先在编译器上安装好ServiceStack服务框架模板,建立新的工程之后,整个项目的目录如图(Yibaobao.BasicComponents是我自己定义的基础组件程序集,并不是框架提供):

按照ServiceStack服务框架建立好一个项目之后,我们就可以根据我们的实际需求来定义我们的服务接口以及相应的数据模型,ServiceStack的具体实现这里就不做赘述,在这里我们就讲解跨域的解决部分,在Service层目录里面有一个“AppHost.cs”文件,在这里面我们可以对我们的WebService做一些设置,比如我们的跨域支持也是在这里完成,改写“AppHost.cs”文件的代码如下:
using Funq;
using ServiceStack;
using Yibaobao.WebService.ServiceInterface;
using System.ServiceModel;
namespace Yibaobao.WebService
{
public class AppHost : AppHostBase
{
/// <summary>
/// Default constructor.
/// Base constructor requires a name and assembly to locate web service classes.
/// </summary>
public AppHost()
: base("Yibaobao.WebService", typeof(MyServices).Assembly)
{ } /// <summary>
/// Application specific configuration
/// This method should initialize any IoC resources utilized by your web service classes.
/// </summary>
/// <param name="container"></param>
public override void Configure(Container container)
{
base.SetConfig(new HostConfig
{
GlobalResponseHeaders = {
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
{ "Access-Control-Allow-Headers", "Content-Type" },
},
}); }
}
}
在重写的Config函数里面也是加了一个响应标头,和配置IIS服务器感觉类似,只是这是在代码中直接解决。
如有什么问题或是错误,请大家多多指正。
关于WebService、WebApi的跨域问题的更多相关文章
- asp.net core webapi之跨域(Cors)访问
这里说的跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作 ...
- 简析ASP.NET WebApi的跨域签名
之前的文章写了关于WebApi的跨域问题,当中的方法只是解决了简单请求的跨域问题而非简单请求的跨域问题则没有解决. 要弄清楚 CORS规范将哪些类型的跨域资源请求划分为简单请求的范畴,需要额外了解几个 ...
- .NET压缩图片保存 .NET CORE WebApi Post跨域提交 C# Debug和release判断用法 tofixed方法 四舍五入 (function($){})(jQuery); 使用VUE+iView+.Net Core上传图片
.NET压缩图片保存 需求: 需要将用户后买的图片批量下载打包压缩,并且分不同的文件夹(因:购买了多个用户的图片情况) 文章中用到了一个第三方的类库,Nuget下载 SharpZipLib 目前用 ...
- webapi支持跨域访问
写在前面 在实际应用中,跨域请求还是比较常见的,如何上接口直接支持跨域的访问呢? demo 场景项目A有个接口用来获取用户列表,现在项目b也有个功能需要加载用户列表.这两个项目在两个域名下,至少端口好 ...
- webapi+ajax跨域问题及cookie设置
最近小玩了点东西,发现简单的东西总能遇到点问题 1.webapi跨域设置 [EnableCors(origins: "*", headers: "*", met ...
- .net core webapi+vue 跨域访问
最近在做一个前后端分离的示例,以下代码完美解决跨域的问题 一.后端服务 1.首先我们建一个.net core webapi的项目 2.项目引用Microsoft.AspNetCore.Cors 包 3 ...
- WebAPI的跨域访问CORS三种方法
跨域访问: JSONP的原理利用<script>没有跨域访问的限制,利用<script>的src跨域访问api,api会根据数据把json包装在一个js里面,这样跨域的客户端拿 ...
- 后端调用接口在通过webService发布 解决跨域问题
1.新建一个空的项目 2.添加一个WebService新项 asmx格式的 3.在这里面写方法 加上[WebMethod]标识 前端就可以调用 4.发布WebService 右键服务 添加服 ...
- C# WebAPI设置跨域
设置前端跨域请求很简单,只需要两个步骤 1.安装package Install-Package Microsoft.AspNet.WebApi.Cors 2.WebApiConfig类中,Regist ...
随机推荐
- VC++中解决“在查找预编译头使用时跳过”的方法
Visual C++ Concepts: Building a C/C++ ProgramCompiler Warning (level 1) C4627Error Message": sk ...
- spdlog源码阅读 (2): sinks的创建和使用
2. sink创建 2.1 还是rotating_file_sink 我们仍然以rotating_file_sink为例来说明在spdlog中sink的创建过程. 在spdlog-master/tes ...
- JAVA基础知识(2)--关键字final的使用
/***Final关键字的使用*@author lihaiming*Email:912547587@qq.com*关键字Final可以修饰属性,方法,类*修饰属性的时候,final修饰的变量是一个常量 ...
- (22)Properties,这不会Io流中的类,但是通常和IO流中的一些流配合使用
可以和流相关联的集合对象Properties. Map |--Hashtable |--Properties Properties:该集合不需要泛型,因为该集合中的键值对都是String类型.既然是m ...
- 【树莓派】Linux 测网速及树莓派源
这篇文章比较杂,其中包含三点:linux环境中测试网络速度,树莓派下载软件的源,部分我写好的脚本: 一.Linux 测网速 Linux 测网速: sar -n DEV 1 100 1代表一秒统计并显示 ...
- Android开发遇到手机无法弹出Toast
今天遇到了一个很奇怪的问题,一个很简单的程序,就是点击按钮弹出一个Toast,但在手机上运行起来,却没有正常弹出Toast 第一反应就是看看是否调用了show方法,很显然,并不是这个低级问题,为了确定 ...
- 《Django By Example》第十章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译本章过程中几次想放弃,但是既然 ...
- PHP和js实时倒计时
<?php //这是t.php页面 header('content-type:text/html;charset=utf-8'); date_default_timezone_set('PRC' ...
- java数组、java.lang.String、java.util.Arrays、java.lang.Object的toString()方法和equals()方法详解
public class Test { public static void main(String[] args) { int[] a = {1, 2, 4, 6}; int[] b = a; in ...
- Legendary Items-微软实习生笔试第一题
题目如下: 这道题难点不仅在于正确理解题意,判断递归条件,更在于用数学方法推出解决公式.因为N最大为1百万,而内存只有256MB, 所以暴力递归肯定会超时,超空间. 不过,我才疏学浅,又没有大量时间去 ...