本篇包括以下内容:

  • CORS 定义
  • CORS 对比 JSONP
  • CORS,BROWSER支持情况
  • 主要用途
  • Ajax请求跨域资源的异常
  • CORS 实现思路
  • 安全说明
  • CORS 几种解决方案
    • 自定义CORSFilter
    • Nginx 配置支持Ajax跨域
    • 支持多域名配置的CORS Filter

keyword:cors,跨域,ajax,403,filter,RESTful,origin,http,nginx,jsonp

转载自:http://www.cnblogs.com/sloong/p/cors.html

CORS 定义

Cross-Origin Resource Sharing(CORS)跨来源资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。

CORS是W3c工作草案,它定义了在跨域访问资源时浏览器和服务器之间如何通信。CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。W3C CORS 工作草案
同源策略:是浏览器最核心也最基本的安全功能;同源指的是:同协议,同域名和同端口。精髓:认为自任何站点装载的信赖内容是不安全的。当被浏览器半信半疑的脚本运行在沙箱时,它们应该只被允许访问来自同一站点的资源,而不是那些来自其它站点可能怀有恶意的资源;参考:JavaScript 的同源策略
JSON & JSONP:JSON 是一种基于文本的数据交换方式,或者叫做数据描述格式。JSONP是资料格式JSON的一种“使用模式”,可以让网页从别的网域要资料,由于同源策略,一般来说位于server1.example.com的网页无法与不是 server1.example.com的服务器沟通,而HTML的script元素是一个例外。利用script元素的这个开放策略,网页可以得到从其他来源动态产生的JSON资料,而这种使用模式就是所谓的JSONP

CORS 对比 JSONP

都能解决 Ajax直接请求普通文件存在跨域无权限访问的问题

  1. JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求
  2. 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理
  3. JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS

CORS,BROWSER支持情况

数据来源:caniuse.com

IE6,IE7,Opera min 不支持CORS。具体可参看数据来源中的 'show all'

主要用途

  • From a browser script perspective: By allowing cross-domain requests, which are subject to tighter controls on the types of data that is exchanged. Cookies, for instance, are blocked unless specifically requested by the XHR author and allowed by the cross-domain web service. This is done to mitigate the risk of data leaks.
  • From a web service perspective: By utilising the origin URL reported by the browser the target cross-domain web service can determine, based on its origin policy, whether to allow or deny the request.

Ajax请求跨域资源的异常

当出现如下异常时,那么就需要考虑跨域的问题了
例如 localhost:63343 通过Ajax请求http://192.168.10.61:8080服务器资源时就会出现如下异常:

CORS 实现思路

CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否

安全说明

CORS is not about providing server-side security. The Origin request header is produced by the browser and the server has no direct means to verify it.

CORS 并不是为了解决服务端安全问题,而是为了解决如何跨域调用资源。至于如何设计出 安全的开放API,却是另一个问题了,这里提下一些思路:

  1. 请求时间有效性(验证timestamp与服务接到请求的时间相差是否在指定范围内,比如5分钟内)
  2. token验证
  3. ip验证
  4. 来源验证

例如

    {
'name': 用户名,
‘key: 加密的验证key,//(name+secret+timestamp来通过不可逆加密生成)
‘timestamp’: 时间戳,//验证timestamp与服务接到请求的时间相差是否在指定范围内,比如5分钟内
}

CORS 几种解决方案

CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否.

Access-Control-Allow-Origin:指定授权访问的域
Access-Control-Allow-Methods:授权请求的方法(GET, POST, PUT, DELETE,OPTIONS等)

一:简单的自定义CORSFilter / Interceptor

适合设置单一的(或全部)授权访问域,所有配置都是固定的,特简单。也没根据请求的类型做不同的处理

在web.xml 中添加filter

<filter>
<filter-name>cros</filter-name>
<filter-class>cn.ifengkou.test.filter.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cros</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

新增CORSFilter 类

@Component
public class CORSFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Access-Control-Max-Age", "1800");//30 min
filterChain.doFilter(request, response);
}
}

Access-Control-Allow-Origin只能配置 或者一个域名*
比如配置了192.168.56.130,那么只有192.168.56.130 能拿到数据,否则全部报403异常

response.addHeader("Access-Control-Allow-Origin", "http://192.168.56.130");

二:Nginx 配置支持Ajax跨域

这里是一个nginx启用COSR的参考配置:来源

#
# Wide-open CORS config for nginx
#
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}

三:支持多域名配置的CORS Filter

因为知道已经有可以用的库可以解决,所以就没重复造轮子了。其实因为懒,看看别人的源码算了。。。

mvnrepository搜索cors-filter,目前也就两个可以用

这两个也都大同小异,因为ebay开源在github上,也有详细的README,那么就以ebay的cors-filter为例

配置

添加依赖包到项目:

<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<version>1.0.1</version>
</dependency>

添加配置(具体配置项,还是见项目的README.md吧)

<filter>
<filter-name>CORS Filter</filter-name>
<filter-class>org.ebaysf.web.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>http://192.168.56.129,http://192.168.56.130</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

源码分析

源码地址:github。但通过IDEA Decompiled 出来的更清晰.....,以下是反编译的

ebaysf的cors-filter 只有一个类CORSFilter。也就是一个拦截器,implements Filter

public final class CORSFilter implements Filter {

通过是实现Filter 的init 方法从配置文件中读取参数:

public void init(FilterConfig filterConfig) throws ServletException {
this.parseAndStore("*", "GET,POST,HEAD,OPTIONS", "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers", "", "true", "1800", "false", "true");
this.filterConfig = filterConfig;
this.loggingEnabled = false;
if(filterConfig != null) {
String configAllowedOrigins = filterConfig.getInitParameter("cors.allowed.origins");
String configAllowedHttpMethods = filterConfig.getInitParameter("cors.allowed.methods");
String configAllowedHttpHeaders = filterConfig.getInitParameter("cors.allowed.headers");
String configExposedHeaders = filterConfig.getInitParameter("cors.exposed.headers");
String configSupportsCredentials = filterConfig.getInitParameter("cors.support.credentials");
String configPreflightMaxAge = filterConfig.getInitParameter("cors.preflight.maxage");
String configLoggingEnabled = filterConfig.getInitParameter("cors.logging.enabled");
String configDecorateRequest = filterConfig.getInitParameter("cors.request.decorate");
this.parseAndStore(configAllowedOrigins, configAllowedHttpMethods, configAllowedHttpHeaders, configExposedHeaders, configSupportsCredentials, configPreflightMaxAge, configLoggingEnabled, configDecorateRequest);
}
}

parseAndStore 方法,解析参数。以 解析cors.allowed.orgins为例;其他参数同理

Set e;
if(allowedOrigins != null) {
if(allowedOrigins.trim().equals("*")) {
this.anyOriginAllowed = true;
} else {
this.anyOriginAllowed = false;
e = this.parseStringToSet(allowedOrigins);
this.allowedOrigins.clear();
this.allowedOrigins.addAll(e);
}
}
//parseStringToSet
//对多域名用点分割,加到HashSet中,再赋给allowedOrigins(Collection<String> allowedOrigins = new HashSet();)
private Set<String> parseStringToSet(String data) {
String[] splits;
if(data != null && data.length() > 0) {
splits = data.split(",");
} else {
splits = new String[0];
} HashSet set = new HashSet();
if(splits.length > 0) {
String[] arr$ = splits;
int len$ = splits.length; for(int i$ = 0; i$ < len$; ++i$) {
String split = arr$[i$];
set.add(split.trim());
}
} return set;
}

如何实现 doFilter

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if(servletRequest instanceof HttpServletRequest && servletResponse instanceof HttpServletResponse) {
HttpServletRequest request1 = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
//识别request 属于哪种类别
CORSFilter.CORSRequestType requestType = this.checkRequestType(request1);
if(this.decorateRequest) {
decorateCORSProperties(request1, requestType);
} switch(CORSFilter.SyntheticClass_1.$SwitchMap$org$ebaysf$web$cors$CORSFilter$CORSRequestType[requestType.ordinal()]) {
case 1:
this.handleSimpleCORS(request1, response, filterChain);
break;
case 2:
this.handleSimpleCORS(request1, response, filterChain);
break;
case 3:
this.handlePreflightCORS(request1, response, filterChain);
break;
case 4:
this.handleNonCORS(request1, response, filterChain);
break;
default:
this.handleInvalidCORS(request1, response, filterChain);
} } else {
String request = "CORS doesn\'t support non-HTTP request or response.";
throw new ServletException(request);
}
}
判断request类别,根据类别进行差异化处理。handleSimpleCORS 处理过程,判断是否设置允许所有origin参数,判断是否符合httpMethods要求,判断此次request的origin(origin = request.getHeader("Origin"))是否在allowedOrigins(origin白名单)内。如果在,就设置response.addHeader("Access-Control-Allow-Origin", origin);这样也就实现了多域名支持。流程图就不画了...
public void handleSimpleCORS(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
CORSFilter.CORSRequestType requestType = this.checkRequestType(request);
String origin;
if(requestType != CORSFilter.CORSRequestType.SIMPLE && requestType != CORSFilter.CORSRequestType.ACTUAL) {
origin = "Expects a HttpServletRequest object of type " + CORSFilter.CORSRequestType.SIMPLE + " or " + CORSFilter.CORSRequestType.ACTUAL;
throw new IllegalArgumentException(origin);
} else {
origin = request.getHeader("Origin");
String method = request.getMethod();
if(!this.isOriginAllowed(origin)) {
this.handleInvalidCORS(request, response, filterChain);
} else if(!this.allowedHttpMethods.contains(method)) {
this.handleInvalidCORS(request, response, filterChain);
} else {
if(this.anyOriginAllowed && !this.supportsCredentials) {
response.addHeader("Access-Control-Allow-Origin", "*");
} else {
response.addHeader("Access-Control-Allow-Origin", origin);
} if(this.supportsCredentials) {
response.addHeader("Access-Control-Allow-Credentials", "true");
} if(this.exposedHeaders != null && this.exposedHeaders.size() > 0) {
String exposedHeadersString = join(this.exposedHeaders, ",");
response.addHeader("Access-Control-Expose-Headers", exposedHeadersString);
} filterChain.doFilter(request, response);
}
}
}

为了避免对参数一知半解,就把作者的参数描述表贴上来,通过参数表可以了解下header里面各个参数的作用

param-name description
cors.allowed.origins A list of origins that are allowed to access the resource. A '' can be specified to enable access to resource from any origin. Otherwise, a whitelist of comma separated origins can be provided. Ex: http://www.w3.org, https://www.apache.org. Defaults: (Any origin is allowed to access the resource).
cors.allowed.methods A comma separated list of HTTP methods that can be used to access the resource, using cross-origin requests. These are the methods which will also be included as part of 'Access-Control-Allow-Methods' header in a pre-flight response. Ex: GET,POST. Defaults:GET,POST,HEAD,OPTIONS
cors.allowed.headers A comma separated list of request headers that can be used when making an actual request. These header will also be returned as part of 'Access-Control-Allow-Headers' header in a pre-flight response. Ex: Origin,Accept. Defaults: Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers
cors.exposed.headers A comma separated list of headers other than the simple response headers that browsers are allowed to access. These are the headers which will also be included as part of 'Access-Control-Expose-Headers' header in the pre-flight response. Ex: X-CUSTOM-HEADER-PING,X-CUSTOM-HEADER-PONG. Default: None
cors.preflight.maxage The amount of seconds, browser is allowed to cache the result of the pre-flight request. This will be included as part of 'Access-Control-Max-Age' header in the pre-flight response. A negative value will prevent CORS Filter from adding this response header from pre-flight response. Defaults: 1800
cors.support.credentials A flag that indicates whether the resource supports user credentials. This flag is exposed as part of 'Access-Control-Allow-Credentials' header in a pre-flight response. It helps browser determine whether or not an actual request can be made using credentials. Defaults:true
cors.logging.enabled A flag to control logging to container logs. Defaults: false
cors.request.decorate A flag to control if the request should be decorated or not. Defaults: true

测试:

1.服务端准备接口(我的地址是:http://192.168.10.61:8080/api)

@RequestMapping(method = RequestMethod.GET,value = "test")
@ResponseBody
public HashMap<String,Object> getArticles(){
HashMap<String,Object> map = new HashMap<>();
map.put("result","success");
return map;
}

2.过滤器配置(web.xml),配置允许访问的域为:http://192.168.56.129,http://www.website2.com

<filter>
<filter-name>CORS Filter</filter-name>
<filter-class>org.ebaysf.web.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>http://192.168.56.129,http://www.website2.com</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

3.准备测试网页index.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>cors test page</title>
<script src="jquery.min.js"></script>
<script>
function loadData(){
$.ajax({
url: "http://192.168.10.61:8080/api",
type:"GET",
dataType:"json",
timeout:10000,
success:function(data){
$("#result").append(data.result+"<br />");
console.log(data);
},
error:function(e){
$("#result").append(e.statusText+"<br />");
}
});
}
$(function(){
$("#host").append("origin:"+window.location.origin);
});
</script>
</head>
<body>
<button onclick="loadData()">onclick</button>
<div id="host"></div>
<div id="result" style="height:200px;width:100%"></div>
</body>
</html>

4.将index.html发布到nginx(nginx后面也有方案)

index.html 不能直接用浏览器打开运行,虽然可以调用Ajax请求,但是域是file:///path/index.html

虚拟机增加一个网卡地址(原机器IP是192.168.56.129)

ifconfig eth0:0 192.168.56.130

建立两个测试网站

cd home
mkdir /website1 #站点目录
mkdir /website2

将index.html 传输到这两个目录

配置nginx,增加两个server节点

# ----server1 ----
server {
listen 192.168.56.129:80;
server_name www.website1.com;
location / {
root /website1;
index index.html index.htm;
}
}
# ----server2 ----
server {
listen 192.168.56.130:80;
server_name www.website2.com;
location / {
root /website2;
index index.html index.htm;
}
}

重启nginx服务

./nginx -s reload

5.修改本地hosts文件

//hosts文件路径:windows系统一般在C:\Windows\System32\drivers\etc
192.168.56.129 www.website1.com
192.168.56.130 www.website2.com

通过增加虚拟网卡 、nginx代理 和 修改hosts文件,我在本地就有4个网站(域)可以进行测试了,分别是:

  • http://192.168.56.129
  • http://192.168.56.130
  • http://www.website1.com
  • http://www.website2.com

6.测试

准备:

(chrome)打开4个tab,分别进入到上述四个网站,页面打印了当前origin,通过onclick调用Ajax请求,页面布局如下

预期:

  • http://192.168.56.129 SUCCESS
  • http://192.168.56.130 ERROR
  • http://www.website1.com ERROR
  • http://www.website2.com SUCCESS

结果:




符合预期!

建议使用,除了对域的过滤,还做了其他很多操作,比简单的自定义过滤器考虑得周全,例如

this.handlePreflightCORS(request1, response, filterChain);
this.handleNonCORS(request1, response, filterChain);
this.handleInvalidCORS(request1, response, filterChain);

总结

cors在开发WebService、RESTful API 时经常会遇到,在以前可能直接通过jsonp解决,jsonp怎样怎样就不多说了。 总之,CORS技术规范出来这么久了,如果不考虑IE6 IE7的问题,那么还是积极拥抱CORS吧

上文三种解决方案,通过搜索引擎均能找到,但估计大部分都是用的第一种最简单的无脑的Cors Filter处理,第二种方案是通过nginx配置的,并不适合所有Web应用。第三种,考虑得很周全,而且使用方便,如果不考虑造重复轮子,推荐使用。

本文所用的测试工程代码太简单了,就不放github了,直接下载吧,项目下载地址

断断续续写了好几天。

转载自:http://www.cnblogs.com/sloong/p/cors.html

首发于[个人博客](https://ifengkou.github.io),转载或引用请附带原文链接,如果文章有摘录和参考,请勿删除文后的[参考和摘录] 章节

CORS跨域实现思路及相关解决方案的更多相关文章

  1. CORS 跨域 实现思路及相关解决方案

    本篇包括以下内容: CORS 定义 CORS 对比 JSONP CORS,BROWSER支持情况 主要用途 Ajax请求跨域资源的异常 CORS 实现思路 安全说明 CORS 几种解决方案 自定义CO ...

  2. 跨域的另一种解决方案——CORS(Cross-Origin Resource Sharing)跨域资源共享

    在我们日常的项目开发时使用AJAX,传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求.浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片 ...

  3. 跨域的另一种解决方案CORS(CrossOrigin Resource Sharing)跨域资源共享

    在我们日常的项目开发时使用AJAX,传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求.浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片 ...

  4. (转)跨域的另一种解决方案——CORS(Cross-Origin Resource Sharing)跨域资源共享

    在我们日常的项目开发时使用AJAX,传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求.浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片 ...

  5. cors跨域和jsonp劫持漏洞 和 同源策略和跨域请求解决方案

    cors跨域和jsonp劫持漏洞: https://www.toutiao.com/a6759064986984645127/ 同源策略和跨域请求解决方案:https://www.jianshu.co ...

  6. 浏览器的同源策略及CORS跨域解决方案 DRF

    一个源的定义 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源. 举个例子: 下表给出了相对http://a.xyz.com/dir/page.html同源检测的示例: UR ...

  7. jsonp与cors跨域的一些理解(转)

    CORS其实出现时间不短了,它在维基百科上的定义是:跨域资源共享(CORS )是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,允许网页从不同的域访问其资源.而这种访问是被同源策略所禁止的. ...

  8. jsonp与cors跨域的一些理解

    浏览器的同源策略,即是浏览器之间要隔离不同域的内容,禁止互相操作. 比如,当你打开了多个网站,如果允许多个网站之间互相操作,那么其中一个木马网站就可以通过这种互相操作进行一系列的非法行为,获取你在各个 ...

  9. spring boot / cloud (六) 开启CORS跨域访问

    spring boot / cloud (六) 开启CORS跨域访问 前言 什么是CORS? Cross-origin resource sharing(跨域资源共享),是一个W3C标准,它允许你向一 ...

随机推荐

  1. 浏览器根对象window之performance

    W3C性能小组引入的新的API,目前IE9以上的浏览器都支持. 为了解决当前性能测试的困难,W3C推出了一套性能API标准,各种浏览器对这套标准的支持如今也逐渐成熟起来.这套API的目的是简化开发者对 ...

  2. Eclipse调试不能进入断点

    Eclipse下在给行设置断点或者在调试时弹出错误“Unable to install breakpoint due to missing line number attributes,Modify ...

  3. SQL 语句及关键字的用法

    一.SELECT select [ALL|DISTINCT] select_list [into new table] FROM table_source [where serch_conditaio ...

  4. ASP.net Substitution 页面缓存而部分不缓存的实现方法

    在ASP.NET中要实现部分内容非缓存,而其它的都需要缓存输出,可以使用Substitution控件实现. <%@ Page Language="C#" AutoEventW ...

  5. [翻译] JTBorderDotAnimation

    JTBorderDotAnimation https://github.com/jonathantribouharet/JTBorderDotAnimation JTBorderDotAnimatio ...

  6. [Swift] 使用Playground

    使用Playground 1. 新建Playground 2. 写最简单的代码

  7. 什么是TTL值?(简单明了的解释)

    什么是TTL值? TTL值全称是“生存时间(Time To Live)”,简单的说它表示DNS记录在DNS服务器上的缓存时间. 要理解TTL值,请先看下面的一个例子:假设,有这样一个域名myhost. ...

  8. 在 Windows Server Container 中运行 Azure Storage Emulator(一):能否监听自定义地址?

    我要做什么? 改 ASE 的监听地址.对于有强迫症的我来说,ASE 默认监听的是 127.0.0.1:10000-10002,这让我无法接受,所以我要将它改成域名 + 80 端口的方式: 放到容器中. ...

  9. CSMA/CD 3

    一.二进制指数类型退避算法 (truncated binary exponential type) 发生碰撞的站在停止发送数据后,要推迟(退避)一个随机时间才能再发送数据. 目的:重传时再次发生碰撞的 ...

  10. [EffectiveC++]item04:Make sure the objects are initialized before they're used

    28 页 C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前. 构造函数的一个较佳的写法是,使用所谓的member initialization list替换赋值动作. 29页 但请立下 ...