JS跨域
同源策略
浏览器出于安全方面的考虑,只允许本域下的接口交互;不同源的客户端脚本不允许相互访问
注意: 是浏览器阻止的
本域:
- 同域名
- 同协议
- 同端口
跨域的几种实现
1. JSONP
原理:利用script标签不受同源策略的限制,来达到与第三方通讯的目的;
操作:在需要通讯时,就创建一个script标签,然后将src指向第三方的API网址,并提供一个回调函数来接收数据(函数名可约定,或通过地址参数数据传递),第三方网站接收到请求后,将数据放到接收到的回调函数中,然后将其返回,本地网站接收到回应后,就执行回调函数,处理接收到的数据;
代码示例:
本地请求
document.querySelector('.change').addEventListener('click', function(e){
var script = document.createElement('script');
// 将回调函数放到callback参数中,当服务器拿到callback后,就将其组成一个函数,并将数据放到该函数中
script.src = 'http://127.0.0.1:8080/getNews?callback=appendHtml';
document.head.appendChild(script);
document.head.removeChild(script);
}, false);
function appendHtml(news) {
var fragment = document.createDocumentFragment();
console.log(news);
var html = '';
news.forEach(function(val){
html += '<li>' + val + '</li>';
});
document.querySelector('.news').innerHTML = html;
}
服务器端
var cb = req.query.callback;
if(cb){
// 注意这一步(重要):
// 将接收收到的callback,组成一个函数,然后将数据放在里面并返回,浏览器端接收到该响应后,就调用回到函数,处理数据
res.send(cb + '('+ JSON.stringify(data) + ')');
}else{
res.send(data);
}
2. CROS(跨域资源请求Cross-Origin Resourse Sharing)
定义: 允许浏览器跨域向服务器发送XMLHttpRequest请求,从而克服ajax只能同源(同协议、同域名、同端口)使用的限制;
注意:CROS分为简单请求和非简单请求,
- 简单请求:HEAD、GET、POST
- 非简单请求:在正式通信之前会增加一次HTTP查询请求,称为“预检”,用于确定网页地址是否在服务器允许范围内,如果在,就继续发送XMLHttpRequest,否则报错;
非简单请求包括:PUT或DELETE,或者Content-Type字段里包括application/json
简单请求操作原理:
- 浏览器端:当浏览器检测到当前请求为跨域请求时,就会在Header里面添加origin字段用于说明,origin字段中包含当前请求的信息(协议,域名和端口)
- 服务器端:当服务接收到请求时,就会检查origin字段中的信息,如果origin指定的源在服务器的允许范围之内,服务器就会在HTTP回应中添加
Access-Control-Allow-Origin
字段,浏览器检测到有这个字段之后就会处理该回应;
如果origin指定的源不在服务器的允许范围之内,服务器就返回正常的HTTP回应,浏览器发现没有Access-Control-Allow-Origin
字段,就会抛出错误,该错误会被XMLHttpRequest的onerror回调函数捕获
特点:
- 需要浏览器和服务器都支持
- 整个过程无需用户介入,全程由浏览器处理,整个代码跟ajax同源请求一样
与JSONP的对比
- JSONP只支持GET请求,CROS支持所有HTTP请求
- JSONP的优势在于支持老式浏览器,以及可以向不支持CROS的网站请求数据
3. 降域
当两个页面使用同一个基础域名,相同协议、相同端口,可以使用降域来实现跨域访问,通过设置:
window.domain = 主域名
来实现,
如下代码:
页面A的URL: http://a.smallmage.com/a.html
页面B的URL: http://b.smallmage.com/a.html
设置它们两个页面的:window.domain = "smallmage.com"
4. 使用HTML5的window.postMessage
方法来跨域传输数据
适用于:两个iframe或两个页面之间
特点:无论是否同源,都可以使用它向其他页面发送数据
参考: 跨域的几种实现
Ajax
定义: 是一种通过js异步获取数据,进行页面的局部刷新的技术。
优点:
- 不需要刷新整个页面来更新数据
- 异步与服务器通信,不需要打断用户操作
- 前后端负载均衡,可以按需取数据,减少带宽
缺点:
- 干掉了back和history功能,对浏览器机制的破坏
浏览器不能记录页面的局部变化
手写一个ajax请求
var xhr = new XMLHttpRequest();
var url = "http://api.jirengu.com/fm/getChannels.php";
// true 表示异步
xhr.open('get', url, true);
xhr.onreadystatechange = function( ) {
// 表示一次ajax结束
if (xhr.readyState === 4) {
console.log(xhr.status);
if (xhr.status >= 200 && xhr.status < 300) {
console.log(JSON.parse(xhr.responseText));
}
}
}
xhr.send();
xhr.readyState的值:
- 0:open()没有被调用,请求没有建立
- 1:open()被调用,请求建立了
- 2:send()被调用,响应头和status已经有效
- 3:响应数据接收到了
- 4:一个请求结束
xhr.status的值:
- 100:响应正常
- 200:请求成功
- 300 :重定向
- 400:客户端数据错误
- 500:服务器端响应错误
HTTP
HTTP是什么?
HTTP是超文本传输协议,用于客户端与服务器进行超文本数据传输的一种协议,构建于TCP/IP协议之上
HTTP版本
总共有:HTTP0.9 、HTTP1.0、HTTP1.1(应用最广泛)、HTTP2.0(还未大规模应用)
HTTP0.9特点:
- 只能发送一行命令
- 回应的是HTML文件
- 回应完成后立马断开连接
HTTP1.0特点:
- 支持多行命令
- 每完成一次Request / Response 就断开连接(特性)
- 缺点:因为每完成一次连接就要断开,因此效率低
HTTP1.1特点:
- 最大的改变是:有了持续连接
- 必须添加Request Header
HTTP方法
- GET:用于请求资源
- POST:向服务器发送私密数据
- PUT:向服务器写入资源(是写入到服务器中,一般服务器都不会开放该功能)
- HEAD:获取网页的信息(就是网页的参数信息),不是网页的内容
- OPTIONS:请求Web服务器支持的方法
HTTP请求的状态码
- 100 :连接已建立
// 2xx 表示请求成功
- 200:请求成功
- 206:服务器成功处理部分GET请求
// 3xx 一般是重定向
- 301:永久重定向
- 302:临时重定向
- 304:资源没有改变,从缓存中获取
// 4xx:客户端请求错误
- 404:找不到资源(客户端请求了不存在的资源)
- 403:有资源,但没有访问权限
// 5xx:服务器端错误
- 500:服务器内部错误
- 502:错误网关
- 503:服务器不可用,通常是服务器超载或停机维修,暂时性的
- 504:网关超时
现在最常用的是HTTP1.1,最新版是HTTP2.0
报文的组成
报文分为:请求报文和响应报文
请求报文
由四部分组成: 请求行、header、空行、请求主体
请求行:
由:方法、URL和HTTP协议三部分组成,例如: GET /index.html HTTP/1.1
header:
header是最重要的部分,包含了请求的所有参数信息,它由key/value
键值组成,每行一对,用 “:
”隔开,如下:
User-Agent: 客户端类型
Accpt: 客户端可识别的内容类型列表
Host: 主机名
还有cookie,缓存相关的参数信息
空行:
发送回车符和换行符,用来说明header结束,接下来是请求主体
请求主体:
请求主体一般用于存放传输给服务器的数据
对GET请求,不存在请求主体,因为GET请求的数据都放在URL中传递过程
只有POST请求才有请求主体
响应报头
包含三部分:状态行、消息报头和响应正文
缓存
问题:面试题」简述浏览器缓存是如何控制的?
该问题考察的是浏览器访问已经访问过的页面时,如何控制缓存
步骤一:当浏览器对某个资源的请求命中了强缓存时,则从缓存中取
强缓存的命中主要通过以下两种方式来确定:
- [Expires]:过期时间,它是一个绝对时间,使用的是客户端的时间,当浏览器需要去访问页面时,先从浏览器缓存中获取该页面的Expires,与客户端的当前时间进行比较,没有过期,则击中缓存,直接取缓存,如果过期,则需要进行下一步:判断是否从服务器端获取缓存
注意:因为用户可以随便更改客户端时间,导致其失效,因此需要下一种方法 - [cache-control => max-age]:是一个相对时间, 最大有效时间, 单位是s, 优先级比expires高, 为了解决expires时间差的问题而出现的
步骤二:没有命中强缓存,则需要发送一个请求到服务器,验证协商缓存是否命中,如果命中,则还是从客户端缓存中加载。协商缓存利用的是[last-modify, if-modify-since]和[ETag, if-not-match]这两对header来管理:
[Last-Modified,if-modify-since]:浏览器请求服务器的数据时,服务器会在响应中添加一个Last-Modified字段,表示最近一次修改缓存的时间,浏览器拿到该字段后,如果发现缓存过期了,它就会将当前请求时间放到if-modify-since中,服务器拿到if-modify-since之后,将其与被请求资源的修改时间进行比较,如果过期,则响应整个资源;没有过期,则响应304;
[ETag, if-not-match]:因为Last-modified只能精确到秒,当资源在短时间内被更改多次时,就无法被检测,因此出现了ETag;浏览器请求服务器数据时,服务器会在响应中添加ETag字符串,该字符串中的信息是对请求资源的编码,当请求资源被改变时,它也会被改变,浏览器判断缓存过期后,如果发现响应头中有ETag,则会将ETag的信息添加到if-not-match中,服务器拿到该数据后,与最新生成的ETag进行对比,如果发现缓存更新,则响应最新的资源信息,否则响应304
性能优化
为什么要性能优化?
- 让页面加载速度更快
- 用户体验更好
- 操作更流畅
性能优化的方法?
主要可以分为三块来进行
加载速度优化
为什么加载速度慢呢?导致的原因:文件太大、请求太多
文件压缩
- 压缩图片
- js、html和css压缩
- 服务器端开启gzip,那么服务器传输的文件就是经过压缩的文件,到了浏览器端会自动解压缩
减少http请求
- 合并js、css,将通用的合并在一起,减少请求,同时可以利用缓存
- 可以利用图片sprite
- 将资源放在多个域名下,提高并发
服务器端的改善
- 添加多个静态资源服务器
- 增加CDN
代码的优化
- 减少DOM操作
- 使用事件代理绑定事件
- 函数节流
体验的优化
- 图片懒加载,分页
- 功能懒加载(html和css先加载,js最后再加载)
Webpack、gulp、requirejs的区别
网络攻击
XSS
XSS(Cross-Site-Scripting):跨站脚本
原理: 在有用户输入的地方,使用一个脚本替换掉用户输入的内容,当用户提交时,如果后端没有对数据进行处理,而是原样输出给前端,那么恶意脚本就会运行,利用XSS插入恶意脚本,可以获取到用户的个人信息,如cookie
防范:
- 后端在输出信息页面时,对输入的数据进行处理,将可疑的“<”转换为html实体
- 前端代码
$p.html(content)
或$p = $('<p>'+ content +'</p>')
直接通过这种方式拼HTML,content有可能被替换为脚本插入到html中
解决办法:就是不要自己拼 HTML,尽量使用 text 方法。如果一定要使用 HTML,就把可疑符号变成 HTML 实体。
CSRF
CSRF(Cross Site Request Forgery):跨站请求伪造
原理:攻击者构造网站后台某个功能接口,诱导用户点击或者使用特殊方法让该请求地址自动加载。用户在登录状态下这个请求被服务器端接收会被误以为是合法操作;
防范:
- 客户端防范:对于数据库的修改请求,一律使用POST方法
- 服务器端防范:
- 服务器发送给客户端一个token
- 客户端在提交表单时添加该token
- 服务器段检测接收到的token是否合法,合法则响应,不合法则拒绝
CSRF参考
HTML & CSS部分
- 圣杯布局
- 双飞翼布局
- 流式布局:早期WEB页面中使用,通过%来设置页面宽度,以便适应不同屏幕尺寸,但是里面的高度、文字大小仍然使用px,所以在大尺寸的屏幕下,会出现页面被拉的很大,但是高度、文字却保持不变,所以页面会显得很不协调
- 弹性布局:Flex布局
- 响应式:就是通过媒体查询来根据不同的屏幕大小,对页面进行调整