王洁

开心最重要……^_^

  • 主页
  • 生活
所有文章 友链 关于我

王洁

开心最重要……^_^

  • 主页
  • 生活

针对 web 的攻击技术

2018-04-21

前言

与最初的设计相比,现今的 Web 网站应用的 HTTP 协议的使用方式已经发生翻天覆地的变化。几乎现金所以的 Web 网站都会使用会话的( session )管理、加密处理等安全性方面的功能,而 HTTP 协议内不具备这些功能。 HTTP 就是一个通用的单纯协议机制。因此它具备较多优势,但是在安全性方面则显劣势。

攻击目标

简单的 HTTP 协议本身并不存在安全性问题,因此协议本身几乎不会称为攻击对象。应用 HTTP 协议的服务器和客户端,以及运行在服务器上的 Web 应用等资源才是攻击目标。目前,来自互联网的攻击大多是冲着 Web 站点来的,它们大多把 Web 应用作为攻击目标。

在客户端即可篡改请求

在 Web 应用中,从浏览器那接收到的 HTTP 请求的全部内容,都可以在客户端自由地变更、篡改。
在HTTP请求报文内加载攻击代码,就能发起对Web应用的攻击。通过URL查询字段或表单、HTTP首部、Cookie等途径把攻击代码传入,若这时Web应用存在安全漏洞,那内部信息就会遭到窃取,或被攻击者拿到管理权限。

针对 Web 应用的攻击模式

针对 Web 应用的攻击模式有以下两种:

  • 主动攻击
  • 被动攻击

    1. 以服务器为目标的主动攻击

    主动攻击( active attack )是指攻击者通过直接访问Web应用,把攻击代码传入的攻击模式。由于该模式是直接针对服务器上的资源进行攻击,因此攻击者需要能够访问到那些资源。

主动攻击模式里具有代表性的攻击是SQL注入攻击和OS命令注入攻击

2. 以服务器为目标的被动攻击

被动攻击(passive attack)是指利用圈套策略执行攻击代码的攻击模式。在被动攻击过程中,攻击者不直接对目标Web应用访问发起攻击。

被动攻击通常的攻击模式如下所示:

步骤1:攻击者诱使用户触发已设置好的陷阱,而陷阱会启动发送已嵌入攻击代码的HTTP请求;

步骤2:当用户不知不觉中招之后,用户的浏览器或邮件客户端就会触发这个陷阱;

步骤3:中招后的用户浏览器会把含有攻击代码的HTTP请求发送给作为攻击目标的Web应用,运行攻击代码;

步骤4:执行完攻击代码,存在安全漏洞的Web应用会成为攻击者的跳板,可能导致用户所持的Cookie等个人信息被窃取,登录状态中的用户权限遭恶意滥用等后果。

被动攻击模式中具有代表性的攻击是跨站脚本攻击和跨站点请求伪造。

2.1 利用用户的身份攻击企业内部网络

利用被动攻击,可发起对原本从互联网上无法直接访问的企业内网等网络的攻击。只要用户踏入攻击者预先设好的陷阱,在用户能够访问到的网络范围内,即使是企业内网也同样会受到攻击。

很多企业内网依然可以连接到互联网上,访问Web网站,或接收互联网发来的邮件。这样就可能给攻击者以可乘之机,诱导用户触发陷阱后对企业内网发动攻击。

总结

很意外就这样来到来总结吧,是的,以上只是简单介绍了针对 Web 的攻击技术,其实后面还有很多由于各种原因引发的安全漏洞,比如上文提到的跨站脚本攻击啊,还有 SQL 注入攻击、OS命令注入攻击、会话劫持、点击劫持、 DoS攻击等等,欲知详情,请听下回分解~~~

  • http

展开全文 >>

原生App与javascript交互

2018-03-14

前言

为了方便业务的扩展以及快速的更新迭代,减少更新发布新版本的频率,现在越来越多的 App 内嵌了 web 网页,比如各大平台淘宝、京东、聚划算、灵机妙算等等,那么如何更好的利用两者间的通信呢?这其中自然也就涉及到了原生和网页之间的一些交互,比如支付,钱包,媒体拓展,图片处理,活动页面,用户地理位置网络状态等都能得到原生强有力的支持。

正文

1.andriod 与 javascript 间的交互

1.1 javascript 调用 andriod 代码
  • 通过 WebView 的 addJavascriptInterface()进行对象映射
  • 通过 WebViewClient 的 shouldOverrideUrlLoading () 方法回调拦截 url
  • 通过 WebChromeClient 的 onJsAlert()、onJsConfirm()、onJsPrompt() 方法回调拦截 JS 对话框 alert()、confirm()、prompt() 消息
a.通过 WebView 的 addJavascriptInterface()进行对象映射

需要加载 JS 代码:javascript.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
const msg = {
name: "小小",
age: 18,
sex: 0
};

const params = "js://m.linghit.com?params=" + JSON.stringify(msg);

function callJavaHello() {
// mWebView.addJavascriptInterface(new AndroidtoJs(), "test");
// 上面的代码向html注入了全局的 window.test 的对象,所以我们直接调用即可
if (window.test) {
test.hello(JSON.stringify(msg));
}
}

function callJavaHello2() {
if (window.test) {
var rt = test.hello2("告诉我周杰伦的相关信息?");
// {"name":"周杰伦","age":28}
var jrt = JSON.parse(rt);
alert("姓名:" + jrt.name + "\n年龄:" + jrt.age);
}
}
</script>
</head>
<body>
<button onclick="callJavaHello()" type="button">点击调用 Java 的 hello 方法</button>

<button onclick="callJavaHello2()" type="button">点击调用 Java 的 hello2 方法(该方法有返回值)</button>
</body>
</html>

定义一个与 JS 对象映射关系的 Android 类:AndroidtoJs

WebViewActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 private void initJsJava1() {
//AndroidtoJS类对象映射到js的test对象
mWebView.addJavascriptInterface(new AndroidtoJs(), "test");
}

/**
* 所有的java类都是默认继承Object的
*/
public class AndroidtoJs {

/**
* 定义JS需要调用的方法,被JS调用的方法必须加入@JavascriptInterface注解(为毛要加)
* <p>
* 在API Level < 17时(即4.2版本之前),JS通过WebView暴露的对象,可以访问其任意的public fields(静态方法和实例方法都可以被访问)。
* <p>
* API Level >= 17的设备,那google已经解决了这个问题,通过加上”@JavascriptInterface”注解暴露给JS指定的方法。
* <p>
* 所以意思是如果不加的话,安卓4.2以后的手机不能调用到这个方法
*
* @param msg 参数,此参数只能是简单的整数,浮点数等基本类型,所以其实一般建议传json字符串
*/
@JavascriptInterface
public void hello(String msg) {
showDialog(getRt("JS调用了Android的hello方法,并传递了参数:", msg));
}

@JavascriptInterface
public String hello2(String msg) {
showDialog(getRt("JS调用了Android的hello2方法,并传递了参数:", msg));
JSONObject object = new JSONObject();
try {
object.put("name", "周杰伦");
object.put("age", 28);
} catch (JSONException e) {
e.printStackTrace();
}
return object.toString();
}
}

该方法使用简单,仅需要仅将 Android 对象和 JS 对象映射即可,但存在严重的漏洞问题。漏洞产生原因是:当 JS 拿到 Android 这个对象后,就可以调用这个 Android 对象中所有的方法,包括系统类(java.lang.Runtime 类),从而进行任意代码执行。如可以执行命令获取本地设备的 SD 卡中的文件等信息从而造成信息泄露。

b.通过 WebViewClient 的 shouldOverrideUrlLoading()方法回调拦截 url

原理:

  1. Android 通过 WebViewClient 的回调方法 shouldOverrideUrlLoading ()拦截 url;
  2. 解析该 url 的协议;
  3. 如果检测到是预先约定好的协议,就调用相应方法。

JS 代码:javascript.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title></title>

<script>
function callOverrideUrl() {
// java 的 shouldOverrideUrlLoading 方法一般在从一个页面跳转到另外一个页面会触发调用
// document.location = "https://m.linghit.com";
// 这里如果我们如果认为的不传递http协议的URI,而使用自定义的URI,然后在java代码里面做处理,就可以达到调用java代码的目的
// 这里我们规定scheme为js,host为m.linghit.com,后面带上参数
document.location = params;
}

</script>
</head>

<!-- 点击按钮则调用callAndroid()方法 -->
<body>
<button type="button" id="button1" <button onclick="callOverrideUrl()" type="button">点击调用 shouldOverrideUrlLoading() 方法</button>
</body>
</html>

当该 JS 通过 Android 的 mWebView.loadUrl(“file:///android_asset/javascript.html”)加载后,就会回调 shouldOverrideUrlLoading ()

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 private void initJsJava2() {
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Uri uri = Uri.parse(url);
String scheme = uri.getScheme();
String host = uri.getHost();
String query = uri.getQuery();
String quParams = uri.getQueryParameter("params");
// 判断是不是我们自己制定的协议
if ("js".equals(scheme)) {
// 自己处理
StringBuilder s = new StringBuilder();
s.append("scheme:").append(scheme).append("\n");
s.append("host:").append(host).append("\n");
s.append("query:").append(query).append("\n");
s.append("quParams:").append(quParams);
showDialog(getRt("使用shouldOverrideUrlLoading加上对应的协议拦截url:\n", s.toString()));
return true;
} else if (!scheme.startsWith("http")) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
loadingPageOver = false;
}

@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
loadingPageOver = true;
}
});
}

该方法不存在方式 1 所说的漏洞,但是对于 js 获取 andriod 代码的返回值会比较复杂,需要重新通过 WebView 的 loadUrl ()去执行 JS 方法把返回值传递回去,相关的代码如下:

1
2
3
4
5
6
7
// Android:MainActivity.java
mWebView.loadUrl("javascript:returnResult(" + result + ")");

// JS:javascript.html
function returnResult(result){
alert("result is" + result);
}
c.通过 WebChromeClient 的 onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截 JS 对话框 alert()、confirm()、prompt() 消息

原理:
Android 通过 WebChromeClient 的 onJsAlert()、onJsConfirm()、onJsPrompt()方法回调分别拦截 JS 对话框,得到他们的消息内容,然后解析即可。
常用的拦截是:拦截 JS 的输入框(即 prompt()方法);因为只有 prompt()可以返回任意类型的值,操作最全面方便、更加灵活;而 alert()对话框没有返回值;confirm()对话框只能返回两种状态(确定 / 取消)两个值。

javascript.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>

<script>
function jsPrompt() {
var rt = prompt(params);
// {"name":"周杰伦","age":28}
var jrt = JSON.parse(rt);
alert("姓名:" + jrt.name + "\n年龄:" + jrt.age);
}
</script>
</head>

<!-- 点击按钮则调用jsPrompt() -->
<body>
<button onclick="jsPrompt()" type="button">利用 onJsPrompt() 方法(利用这个可以有返回值)</button>
</body>
</html>

当使用 mWebView.loadUrl(“file:///android_asset/javascript.html”)加载了上述 JS 代码后,就会触发回调 onJsPrompt()。

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private void initJsJava3() {
mWebView.setWebChromeClient(new WebChromeClient() {

@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// message ===> js://m.linghit.com?params={"name":"小小","age":18,"sex":0}
Uri uri = Uri.parse(message);
String scheme = uri.getScheme();
String host = uri.getHost();
String query = uri.getQuery();
String quParams = uri.getQueryParameter("params");
// 判断是不是我们自己制定的协议
if ("js".equals(scheme)) {
// 自己处理
StringBuilder s = new StringBuilder();
s.append("scheme:").append(scheme).append("\n");
s.append("host:").append(host).append("\n");
s.append("query:").append(query).append("\n");
s.append("quParams:").append(quParams);
showDialog(getRt("使用onJsPrompt加上对应的协议:\n", s.toString()));
// 返回值
JSONObject object = new JSONObject();
try {
object.put("name", "周杰伦");
object.put("age", 28);
} catch (JSONException e) {
e.printStackTrace();
}
result.confirm(object.toString());
return true;
}
return super.onJsPrompt(view, url, message, defaultValue, result);
}

});
}
三种方式的对比总结

a 方式方便简洁,安卓 4.2 以下存在漏洞,安卓 4.2 以上相对简单,互调场景
b 方式不存在漏洞问题,使用比较复杂,需要协议的约束,从 Native 层往 web 层传递比较复杂,不需要返回值的时候可用。
c 方式不存在漏洞问题,使用复杂,需要协议的约束,能满足大多数情况下的互调场景。

1.2 andriod 调用 javascript 代码
  • 通过 WebView 的 loadUrl()
  • 通过 WebView 的 evaluateJavascript()
a.通过 WebView 的 loadUrl()

需要加载 JS 代码:javascript.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 文本名:javascript
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title></title>
// JS代码
<script>
// Android需要调用的方法
function callJS(){
alert("Android调用了JS的callJS方法");
}
</script>
</head>

</html>

Android 代码:MainActivity.java

1
2
3
4
5
private void loadurl() {
// javascript:callJS('周杰伦')
String name = "周杰伦";
mWebView.loadUrl("javascript:callJSLoadurl('" + name + "')");
}
b.通过 WebView 的 evaluateJavascript()

相较于第一种方式,这种会效率更高,使用起来更简洁

  1. 因为该方法的执行不会使页面刷新,而第一种方法(loadUrl )的执行则会。
  2. Android 4.4 后才可使用

需要加载 JS 代码:javascript.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 文本名:javascript
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title></title>
// JS代码
<script>
// Android需要调用的方法
function callJSEval(name) {
alert("姓名:" + name);
var elem = document.getElementById("eval");
elem.innerText = "java使用WebView.evaluateJavascript形式调用js代码,并传递了参数:" + name;
return "OK";
}

</script>
</head>

</html>

MainActivity.java

1
2
3
4
5
6
7
8
9
10
@TargetApi(19)
private void eval() {
String name = "王力宏";
mWebView.evaluateJavascript("javascript:callJSEval('" + name + "')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
showDialog(getRt("使用evaluateJavascript()调用js代码并收到返回:\n", value));
}
});
}

使用建议:两种方法混合使用,即 Android 4.4 以下使用方法 1,Android 4.4 以上方法 2

1
2
3
4
5
6
// Android版本变量
if (Build.VERSION.SDK_INT >= 19) {
eval();
} else {
loadurl();
}

2.OC 与 javascript 间的交互

iOS 的 webview 有 2 个类,一个叫 UIWebView,另一个是 WKWebView。两者的基础方法都差不多,本文重点是后者,他是取代 UIWebView 出现的,在 app 开发者若不需要兼容 ios8 之前版本,都应该使用 WKWebVIew。

2.1 javascript 调用 OC 代码
  • 通过拦截 request 的方式间接实现(url 拦截)
  • 使用 JavaScriptCore 的 jsContext 注册 objc 对象或使用 JSExport 协议导出 Native 对象的方式
a.通过拦截 request 的方式间接实现(url 拦截)

比如 linghit://。方法是在 html 或者 js 中,点击某个按钮触发事件时,跳转到自定义 URL Scheme 构成的链接,而 Objective-C 中捕获该链接,从中解析必要的参数,实现 JS 到 OC 的一次交互。比如页面中一个 a 标签,链接如下:

1
<a href="linghit://smslogin?username=xiaoming&code=123456">

当用户点击 a 这个标签时,会被拦截

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
//可以通过navigationAction.navigationType获取跳转类型,如新链接、后退等
NSURL *URL = navigationAction.request.URL;
//判断URL是否符合自定义的URL Scheme
if ([URL.scheme isEqualToString:@"linghit"]) {
//根据不同的业务,来执行对应的操作,且获取参数
if ([URL.host isEqualToString:@"smsLogin"]) {
NSString *param = URL.query;
NSLog(@"短信验证码登录, 参数为%@", param);
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
decisionHandler(WKNavigationActionPolicyAllow);
NSLog(@"%@", NSStringFromSelector(_cmd));
}

优点:泛用性强,可以配合 h5 实现页面动态化。比如页面中一个活动链接到活动详情页,当 native 尚未开发完毕时,链接可以是一个 h5 链接,等到 native 开发完毕时,可以通过该方法跳转到 native 页面,实现页面动态化。且该方案适用于 Android 和 iOS ,泛用性很强。

缺点:无法直接获取本次交互的返回值,比较适合单向传参,且不关心回调的情景,比如 h5 页面跳转到 native 页面等。

b.使用 JavaScriptCore 的 jsContext 注册 objc 对象或使用 JSExport 协议导出 Native 对象的方式

该方法需要在页面加载完成时,先获取 js 上下文。获取到之后,我们就可以进行强大的方法映射了。与上面介绍的安卓通过 WebView 的 addJavascriptInterface() 进行对象映射类同。有兴趣的小火棒课后可以了解。

2.2 OC 调用 javascript 代码
  • 使用 evaluateJavaScript 方法
a.使用 evaluateJavaScript 方法

WKWebView 调用 js 方法和 UIWebView 类似,一个是 evaluateJavaScript,一个是 stringByEvaluatingJavaScriptFromString。获取返回值的方式不同,WKWebView 用的是回调函数获取返回值;而 stringByEvaluatingJavaScriptFromString 直接通过函数返回值,返回调用结果。

1
2
3
4
5
6
7
8
//直接调用js
webView.evaluateJavaScript("hi()", completionHandler: nil)
//调用js带参数
webView.evaluateJavaScript("hello('liuyanwei')", completionHandler: nil)
//调用js获取返回值
webView.evaluateJavaScript("getName()") { (any,error) -> Void in
NSLog("%@", any as! String)
}

总结

上文可知,其实 iOS 和 andriod 与 js 交互原理上是差不多的,实现上也是大同小异,现在更有一些第三方库解决了一些调用上的缺陷,比如 iOS 有 WebViewJavaScriptBridge 啊,andriod 有 JSBridge 等,有兴趣的同学可以去了解研究。。

  • 其它

展开全文 >>

关于HTTPS

2018-01-14

HTTP和HTTPS的基本概念

HTTP: 是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,他可以说浏览器更加高效,是网络传输减少。
HTTPS: 是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

HTTP的缺点

  • 通信使用明文(不加密), 内容可能会被窃听
  • 不验证通信方的身份, 因此有可能遭遇伪装
  • 无法证明报文的完整性, 所有有可能已遭篡改

HTTPS的作用以及与HTTP的区别

HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。即HTTP加上加密处理和认证以及完成性保护后即是HTTPS。
而HTTPS和HTTP的区别主要如下:

  1. https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
  2. http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
  3. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  4. http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

HTTPS的工作原理

HTTPS并非是应用层的一种新协议. 只是HTTP通信接口部分用SLL(Secure Socket Layer)和TLS (Transport Layer Security) 协议替代而已.
通常, HTTP直接和TCP通信, 当使用SSL时, 演变成了先和SSL通信, 再由SSL和TCP通信了, 简而言之, 所谓HTTPS, 其实就是身披SSL协议的这层外壳的HTTP.
在采用SSL后, HTTP就拥有了HTTPS的加密, 证书和完整性的保护这些功能.
SSL是独立于HTTP的协议, 所有不光是HTTP协议, 其他运行在应用层的SMTP(邮件协议)和Telnet等协议均可配合SSL协议使用. 可以说SSL是当今世界上应用最广泛的网络安全技术.

1.客户端发起HTTPS请求

用户在浏览器里输入一个https网址,然后连接到server的443端口。

2.服务端的配置

采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请,区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面。
这套证书其实就是一对公钥和私钥,如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。

3.传送证书

这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。

4.客户端解析证书

这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。
如果证书没有问题,那么就生成一个随机值,然后用证书对该随机值进行加密,就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。

5.传送加密信息

这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。

6.服务段解密信息

服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密,所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。

7.传输加密后的信息

这部分信息是服务段用私钥加密后的信息,可以在客户端被还原。

8.客户端解密信息

客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容,整个过程第三方即使监听到了数据,也束手无策。

HTTPS存在的问题

  • 消耗更多的资源;由于HTTPS还需要做服务器,客户端双方加密及解密处理, 因此会消耗CPU和内存等硬件资源, 和HTTP通信相比, SSL通信部分消耗网络资源. 而SSL通信部分, 有因为要对通信进行处理, 所有时间上又延长了。
  • SSL证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用。
  • SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗(SSL有扩展可以部分解决这个问题,但是比较麻烦,而且要求浏览器、操作系统支持,Windows XP就不支持这个扩展,考虑到XP的装机量,这个特性几乎没用)。
  • HTTPS连接缓存不如HTTP高效,大流量网站如非必要也不会采用,流量成本太高。
  • HTTPS连接服务器端资源占用高很多,支持访客稍多的网站需要投入更大的成本,如果全部采用HTTPS,基于大部分计算资源闲置的假设的VPS的平均成本会上去。
  • HTTPS协议握手阶段比较费时,对网站的相应速度有负面影响,如非必要,没有理由牺牲用户体验。

针对速度慢这样一个问题, 并没有根本性的解决方案, 我们会使用SSL加速器这种(专用服务器)硬件来改善该问题. 相对软件来讲, 能够提高数倍SSL计算速度。
因此, 如果是非敏感信息则使用HTTP通信, 只有在包括个人信息等敏感数据时, 才利用HTTPS加密通信, 以节省资源. 除此之外, 想要节约购买证书的开销也原因之一.

  • http

展开全文 >>

http之http状态码

2017-12-13

前言

本文主要根据以下几点对http进行学习归纳

  • 什么是http状态码
  • http状态码的职责
  • 常见的http状态码及其含义

什么是http状态码

当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头用以响应浏览器的请求。

http状态码的职责

状态码的职责是当客户端向服务器发送请求时,描述返回的请求结果。借助状态码,用户可以知道服务器是正常处理了请求,还是出现了错误。

常见的http状态码及其含义

状态码 类别 原因短语
1** Informational(信息性状态码) 接收的请求正在处理
2** Success(成功状态码) 请求正常处理完毕
3** Redirection(重定向状态码) 需要进行附加操作已完成请求
4** Client Error(客户端错误状态码) 服务器无法处理请求
5** Server Error(服务器错误状态码) 服务器处理请求错误

具体的http状态码及对应含义

  • 100 客户端继续发送请求,这是临时响应的状态码。
  • 101 服务端根据客户端的请求切换协议。(只能切换到更高级的协议)
  • 102 处理将被继续执行
  • 200 服务端已成功处理了请求
  • 201 请求成功并且服务端创建了新的资源。
  • 202 服务端已接受请求但尚未处理。
  • 203 服务端已成功处理了请求但返回的信息可能来自于另一来源。
  • 204 服务端成功处理了请求但没有返回任何内容。
  • 205 服务器成功处理了请求,客户端应重置文档视图。可通过此返回码清除浏览器的表单域。
  • 206 服务器成功处理了部分GET请求。
  • 207 代表之后的消息将会是一个XML消息。
  • 300 服务器可执行多种操作。服务器可根据请求者选择一项操作,或者提供操作列表供请求者选择。
  • 301 永久移动。请求的资源已被永久的移动到新URL。今后任何新的请求都使用新的URL。
  • 302 临时移动。服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
  • 303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
  • 304 (未修改)自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
  • 305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
  • 307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
  • 400 (错误请求) 服务器不理解请求的语法。
  • 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
  • 403 (禁止) 服务器拒绝请求。
  • 404 (未找到) 服务器找不到请求的网页。
  • 405 (方法禁用) 禁用请求中指定的方法。
  • 406 (不接受) 无法使用请求的内容特性响应请求的网页。
  • 407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
  • 408 (请求超时) 服务器等候请求时发生超时。
  • 409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
  • 410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。
  • 411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。
  • 412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。
  • 413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
  • 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
  • 415 (不支持的媒体类型) 请求的格式不受请求页面的支持。
  • 416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。
  • 417 (未满足期望值) 服务器未满足”期望”请求标头字段的要求。
    5开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。
  • 500 (服务器内部错误) 服务器遇到错误,无法完成请求。
  • 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
  • 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
  • 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
  • 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
  • 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
  • http

展开全文 >>

javascript之事件篇

2017-11-16

事件相关概念

  • 事件是与浏览器或文档交互的瞬间,如点击按钮,填写表格等,它是JS与HTML之间交互的桥梁。
  • 事件类型是一个用来说明发生什么类型事件的字符串。例如mousemove”表示用户鼠标移动。
  • 事件目标是发生的事件或与之相关的对象。当讲事件时,我们必须同时指明类型和目标。例如,window上的load事件或者
  • 事件处理程序或事件监听程序时处理或响应事件的函数。应用程序通过指明事件类型和事件目标,在WeLb浏览器中注册它们的事件处理程序函数。
  • 事件对象是与特定事件相关且包含有关该事件的详细信息的对象。事件对象作为参数传递给事件处理程序函数(不包括IE8之前的版本,在这些浏览器中有时仅能通过全局变量event才能得到)。所有事件的对象都有用来指定事件类型的type和指定事件目标的target属性(在IE8之前版本中用srcElement而非target属性)。
  • 事件传播是浏览器决定哪个对象触发其事件处理程序的过程。事件传播有两种形式,一种是事件冒泡,另一种是事件捕获。

事件类型

  1. DOM事件
  2. HTML5事件
  3. 触摸屏和移动设备事件

事件处理程序

  • DOM0级模型
    又称为原始事件模型,在该模型中,事件不会传播,即没有事件流的概念。
  1. 设置javascript对象属性为事件处理程序
1
2
3
4
var btn = document.getElementById('.btn');
btn.onclick = function(){
alert('hello word!')
};

缺点:每个事件目标对于每种事件类型将最多只有一种处理程序。

  1. 设置HTML标签属性为事件处理程序
    这种方式设置事件处理程序,html标签的属性值应该是javascript代码字符串,不应该是用大括号包围且使用function关键字的前缀;如果包含多条javascript语句,必须使用分号隔开或者断开属性值使其跨多行。
1
<input type="button" onclick="alert('hello word!')">

缺点:这种方式将 HTML 代码与 JavaScript 代码耦合在一起,不利于代码的维护,所以应该尽量避免使用这样的方式。

  • DOM2级模型
    属于W3C标准模型,现代浏览器(除IE6-8之外的浏览器)都支持该模型。在该事件模型中,一次事件共有三个过程:
1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>

事件捕获阶段(capturing phase)。事件从document一直向下传播到目标元素, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行。

document->html->body->div

事件处理阶段(target phase)。事件到达目标元素, 触发目标元素的监听函数。

事件冒泡阶段(bubbling phase)。事件从目标元素冒泡到document, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行。

div->body->html->document

addEventListener()

addEventListener()接受三个参数,第一个是注册处理程序的类型;第二个是指定类型的事件发生时应该调用的函数;第三个是布尔值,通常情况下会给这个参数传递false,如果相反传递了true,那么函数将注册为捕获事件处理程序,并在事件不同的调用阶段调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
var btn = document.getElementById('.btn'),
showMessage = function(){
alert('again...')
};
btn.onclick = function(){
alert('hello word !');
}
//事件绑定监听函数
btn.addEventListener(‘click’, showMessage, false);
//事件移除监听函数
btn.removeEventListener(‘click’, showMessage }, false);
```
能通过多次调用addEventListener()为同一个对象注册同一事件类型的多个处理程序函数。当对象上发生事件时,所以该件事件类型的注册处理程序都会按照注册的顺序调用。使用相同的参数在在同一个对象上多次调用addEventListener()是没用的,处理程序仍然只注册一次,同时重复调用也不会改变调用程序处理程序的顺序。

- IE事件模型
#### attachEvent()和detachEvent()的工作原理与addEventListener()和removeEventListener()类似,但有如下例外:
1. IE事件模型不支持事件捕获,所以attachEvent()和detachEvent()只有两个参数:事件类型和处理程序函数。
2. IE方法的第一参数使用了带'on'前缀的事件处理程序属性名。
3. attachEvent()允许相同的事件处理程序函数注册多次。注册函数的调用次数和注册次数一样。
### 事件对象
下面介绍一些比较常用的属性和方法。

target、 srcElement、 currentTarget 和 relatedTarget、fromElement、 toElement
> - target 与 srcElement 完全相同;
> - target 指触发事件的元素, currentTarget 指事件所绑定的元素;
> - relatedTarget: 与事件的目标节点相关的节点。对于 mouseover 事件来说,该属性是鼠标指针移到目标节点上时所离开的那个节点。对于 mouseout 事件来说,该属性是离开目标时,鼠标指针进入的节点。对于其他类型的事件来说,这个属性没有用;
> - fromElement 和 toElement 仅仅对于 mouseover 和 mouseout 事件有效。

clientX/Y、 screenX/Y、 pageX/Y、 offsetX/Y
> - offsetX/Y: 点击位置相对于所处元素左上角的位置;
> - clientX/Y: 点击位置相对于浏览器内容区域左上角的位置;
> - screenX/Y: 点击位置相对于屏幕左上角的位置;
> - pageX/Y: 点击位置相对整张页面左上角的位置;
> - pageX/Y 与 clientX/Y 一般情况下会相同,只有出现滚动条时才不一样。

altKey、 ctrlKey、 shiftKey
> - altKey: 返回当事件被触发时,"ALT" 是否被按下;
> - ctrlKey: 返回当事件被触发时,"CTRL" 键是否被按下;
> - shiftKey: 返回当事件被触发时,"SHIFT" 键是否被按下;

其他属性
> - type: 返回当前 Event 对象表示的事件的名称
> - bubbles: 返回布尔值,指示事件是否是起泡事件类型;
> - cancelable: 返回布尔值,指示事件是否可拥可取消的默认动作;
> - eventPhase: 返回事件传播的当前阶段,有三个值: Event.CAPTURING_PHASE、 Event.AT_TARGET、 Event.BUBBLING_PHASE,对应的值为 1、2、3,分别表示捕获阶段、正常事件派发和起泡阶段;
> - path: 冒泡阶段经过的节点;

方法
> - preventDefault(): 通知浏览器不要执行与事件关联的默认动作;
> - stopPropagation(): 阻止冒泡;

### Event Wrapper

var eventUtils={
// 添加句柄
addHandler:function(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if(element.attachEvent){
element.attachEvent(‘on’+type,handler);
}else{
element[‘on’+type]=handler;
}
},
// 删除句柄
removeHandler:function(element,type,handler){
if(element.removeEventListener){
element.removeEventListener(type,handler,false);
}else if(element.detachEvent){
element.detachEvent(‘on’+type,handler);
}else{
element[‘on’+type]=null;
}
},
//获取事件对象
//IE模型中event是一个全局唯一的对象绑定在window对象上
getEvent:function(event){
return event?event:window.event;
},
//获取类型
getType:function(event){
return event.type;
},
getElement:function(event){
return event.target || event.srcElement;
},
//阻止默认事件
preventDefault:function(event){
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue=false;
}
},
//阻止冒泡
stopPropagation:function(event){
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble=true;
}
}
}
```

小结

事件是将 JavaScript 与网页联系在一起的主要方式。DOM3 级事件规范和 HTML5 定义了常见的大多数事件。即使有规范定义了基本事件,但很多浏览器仍然在规范之外实现了自己的专有事件,从而为开发人员提供更多掌握用户交互的手段。有些专有事件与特定设备关联,例如移动 Safari 中的 orientationchange 事件就是特定关联 iOS 设备的。

在使用事件时,需要考虑如下一些内存与性能方面的问题。

  • 有必要限制一个页面中事件处理程序的数量,数量太多会导致占用大量内存,而且也会让用户感觉页面反应不够灵敏。
  • 建立在事件冒泡机制之上的事件委托技术,可以有效地减少事件处理程序的数量。
  • 建议在浏览器卸载页面之前移除页面中的所有事件处理程序。
  • js基础

展开全文 >>

javascript之this篇

2017-11-12

开门见山,下面我们直入正题,为大家介绍一下关于javascript的this这一指向,首先我想用一句话来概括js中关于this的指向问题:==this它其实既不指向函数自身也不指向函数的词法作用域,this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。==

在正常情况下,下面我们通过绑定的规则把this分为四个规则来介绍:

1、默认绑定(全局上下文)

1
2
3
4
5
6
function foo(){
//"use strict";
console.log(this.a);
}
var a = 2;
foo(); // 2

2、隐式绑定(作为对象的方法调用,闭包)

A、作为对象的方法调用

demo1:

1
2
3
4
5
6
7
8
function foo(){
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); //2

demo2:

1
2
3
4
5
6
7
8
9
10
11
12
13
function foo(){
console.log( this.a );
}
var obj2 = {
a: 42,
foo: foo
};
var obj1 = {
a:2,
obj2: obj2
};

obj1.obj2.foo(); //??

注:对象属性引用链中只有上一层或者说最后一层在调用的位置中起作用

B、闭包(内部函数)
1
2
3
4
5
6
7
8
9
10
11
var a = 'foo';
var person = {
a: 'bar',
hello: function( sth ){
var sayHello = function() {
console.log( this.a +'says' +sth );
};
sayHello(sth);
}
}
person.hello('hello'); //??

这里this的指向跟闭包没有关系,闭包针对于变量来说的。sayHello function is being invoked as a standalone function not attached to any object, and this will refer to the global object.

C、隐式丢失
a、闭包(如上)
b、传入回调函数时
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function foo(){
console.log( this.a );
}
function doFoo( fn ){
//fn其实引用的是foo
fn(); //<-调用位置
}
var obj = {
a: 2,
foo: foo
};
var a = "global a";
doFoo( obj.foo ); //??
//setTimeout(obj.foo,100); //??

注:参数传递其实是一种隐式赋值,所以我们传入函数时也会被隐式赋值,因此应用了默认绑定,就是绑定到全局中去。

3、显式绑定(使用call与apply设置this)

1
2
3
4
5
6
7
function foo(){
console.log( this.a );
}
var obj = {
a: 2
};
foo.call( obj ); //??
A、硬绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function foo(){
console.log( this.a );
}
var obj = {
a:2
};
var bar = function(){
foo.call( obj );
};
bar(); //??
setTimeout( bar,100 ); //??

//硬绑定的bar可能or不可能再修改它的this呢???
bar.call( window ); //??

注:Function.prototype.bind有兴趣可以自己去了解,意思差不多

4、new绑定

1
2
3
4
5
function foo(a){
this.a = a;
}
var bar= new foo(2);
console.log(bar.a); //??

以上四种就是正常情况下的四个判断规则啦,那么有正常的那也就有所例外嘛?是的,你没猜错,真的有例外。

1、当在默认使用call,apply,bind时把null或者undefined作为this的绑定对象传入呢??
2、间接引用?
1
2
3
4
5
6
7
8
function foo(){
console.log( this.a );
}
var a =2;
var o = { a: 3,foo: foo };
var p = { a: 4 };
o.foo(); //3
(p.foo() = o.foo)(); //????
3、软绑定?

哦,对了,还有一个差点忘记了,就是关于ES6的箭头函数啦。
想必聪明机智的你看完下面的这两个函数就会知道我要讲什么了。
es6 demo:

1
2
3
4
5
6
7
8
9
10
function foo(){
setTimeout( () => {
//这里的this在词法上继承自foo();
console.log( this.a );
},100);
}
var obj = {
a: 2
};
foo.call( obj ); //??

非es6 demo:

1
2
3
4
5
6
7
8
9
10
function foo(){
var self = this;
setTimeout(function(){
console.log(self.a);
},100)
}
var obj = {
a: 2
};
foo.call( obj ); //??

总结:

以下是根据正常情况下按照优先级排列的四条规则来判断this的绑定对象:

  • 1、由new调用?绑定到新建的对象
  • 2、由call或者apply(或者bind)调用?绑定到指定的对象
  • 3、由上下文对象调用?绑定到那个上下文对象(就近原则)
  • 4、默认:在严格模式下绑定到undefined,否则绑定到全局对象
  • 还有一些调用可能在无意中使用了默认绑定规则;
  • 还有就是es6的箭头函数并不会使用以上四条规则,而是根据当前的词法作用域来决定this,具体来说,就是会继承外层函数调用的this绑定。

第一次整理这种关于技术的文章,各位将就着看,欢迎批评指正哦!附上美女高清图一张。。(文件过大,无法预览)

  • js基础

展开全文 >>

« Prev12 Next »
© 2020 王洁
Hexo Theme Yilia by Litten
  • 所有文章
  • 友链
  • 关于我

tag:

  • 其它
  • http
  • js基础
  • node

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • ryansuen
  • coalya
  • keminu
  • heyrumour
  • 4096void
  • maizsss
  • yzr006
  • mabiao8023
  • guozexuan
  • shuangmuyingzi
  • hupeip
  • uking2016
  • ning777
一个想要享受生活的程序媛^_^
生活不止敲代码,还有~~~
吃喝玩乐
hahaha