
暂无个人介绍
最近手头接了公司一个方案编写的任务,但一直没有好的思路,虽说以前也写过产品的一些方案,有一定的沉淀,但仔细想来,基于产品的解决方案和基于定制开发的方案应该有很大的不同。所以就通过网络和以前的朋友,找了一些方案,分析对比后,把个人的一些感受写下来,以供大家探讨。不妥之处,还望不吝指出,以便改进。 通过这次方案的编写,我个人有以下体会: 1、用户的需求把握很重要,要找到用户的关注点。 方案编写前,实际上有个用户需求调研的过程,要按咨询的一般流程,对用户目前的业务流程进行描述、分析,象医生之于病人一样,通过望、闻、问、切,找出问题所在,然后对症下药。但由于分工不同,往往我们拿到手的资料很有限,对用户的需求的把握不够,甚至于没有和用户正面接触过,这中间就有很大的风险。怎么办?我个人认为,应该这样处理: 基于有限的有户需求,展开广泛的用户需求讨论,讨论的范围是和这个项目有关联的所有人员,包括销售人员、产品和售前组人员、部门的领导。大家从每个人的认识上,充分挖掘用户的需求,并对挖掘出的用户需求分优先级,然后再在统一的思路下去分别展开具体的方案编写工作。领导说得好“方向对了头,一步一层楼嘛”!最后由产品售前组统一进行方案的优选和整合,在整个方案中,要做到突出重点,要有靓点。 下面给个流程图,是基于咨询的,可以给我们提供参考: 2、站的高度要足够高,要从管理层面的高度,既要有就事论事的详细技术解决方案,更要有领导层面的监控执行和决策分析 好的方案,应该是站在全局的高度,从高管层、管理执行层、业务操作运行层三个层面分别提出决策分析、监督控制及数据采集录入的完整解决方案。这个过程中,许多人只专注于技术,关心技术解决方案,而忽略了高层的分析决策及中层的管理控制功能,这也是方案的大忌。我们一般可以采用由下而上写,由上而下检查,上下结合,统一验证的办法处理。 3、先搭框架,再逐步细化 遵循一般问题分析方法,先构建整体框架(参考14一般解决方案模板),然后再提取总的解决方案,再逐步细化,最终抽象出具体的支持方案的模块,接下来再按由下而上的流程,对流程进行验证、修改,保证高层、中层及业务层在数据源、数据结构及业务逻辑上的统一性,最后对每个模块的特点、靓点做详细地描述。 4、方向要明确,最好从管理角度切入,不能单纯的就事论事 做方案时要记住,我们提供给用户的是总体解决方案,不只是单纯的技术方案,用我们熟悉的成熟的技术,加上优化的用户的流程,结合用户总体战略,就可以编制出满足用户需求的方案。 5、最好有参考的方案,做好平常的知识积累 我们遇到的客户,需要解决的问题是各不相同、有时甚至是跨行业的,这就要求我们的售前和需求人员要加强平时的学习和积累。一些好的方案,特别是知名咨询公司的方案,是对我们有启发意义的。平时加强优秀方案的学习,积累一般问题的解决方案,可以使我们有更多的精力关注于具体用户的个性需求,用信息化实现用户个性管理思想,这也为用户最为关注和推崇的,而这个过程的实现,实际上是个双赢的过程,实现上知识的双向转移。 6、最好的方案,是无招胜有招的境界 我们在现实生活中,常遇到这样的情况,许多IT公司的高层,并不是学习计算机专业出身的,看似外行管内行的情况普遍存在。但只要你深入地思考一下,实际上做到一定的程度,在有了广泛知识积累后,就发现各行业总是相通之处的,正是由于他们有了知识转移和复用的能力,高度决定了他们的视野,武功的最高境界是无招胜有招,这决不是空谈。只要你用心去想,这个道理大家都能想通。具体到我们的方案,针对每一个CASE,我们都力争提取出共性的一面,这样,我们的水平也就提高到了另外一种境界。 7、别小看细节和形式 “泰山不拒细壤,故能成其高;江海不择细流,故能就其深”。所以,大礼不辞小让,细节决定成败。我们在方案编写过程中,也要注意细节,比如良好的组织形式,清晰的思路,严谨地措辞,都会使我们的方案添彩,反之,如果一个方案中错别字充斥其中,想想阅读者会有怎么样的感受。还有一点,我们在做给客户的方案中,不能用外行话,涉及到行业的专业术语,如果不懂,不妨GOOGLE或BAIDU一下,网络不是只用来看优酷,看新闻的,网络极大的降低了我们的学习成本,这么好的平台,我们何乐而不为呢! 8、与其面面俱到,不如靓点突出 以点带面,突出靓点。我们做任何事情,都不可能做到尽善尽美。但在方案中一定要突出我们的靓点,突出我们与众不同的一面。对于系统的靓点,我们要不吝笔墨,详细描述,力争用户一想到我们,就想到我们的系统是什么样子,如果做到这一点,方案的胜出也就是顺理成章的事情了。 9、需求和售前人员要勤于思索,凡事怕琢磨 我们不但要站在IT技术的角度,更要从客户的业务角度,以换位思考的方法,以不同的客户角色的身份,阐述实现方案能给用户带来什么,做详细地说明。是降低成本呢?还是方便工作、降低工作强度?是给领导还来决策支持呢?还是提高生产效率?对系统的经济效益进行多维度分析。我们可以设想系统运行的全过程,不断地思考,反复地修订,直到最终定稿。 10、 没有思路的时候,别强行下手 11、实事求是不可忘,可以略带发挥,但不能天花乱坠,不能让用户一看这根本就实现不了,是在做秀。 12、不断学习很重要,不怕不懂,就怕不学。 13、最忌照抄,做事要用心,方案出新,逻辑性要强 这实际上是网络资源的一种滥用,有时转贴或参考一下别人的方案,无可厚非,但如果滥用别人的方案,或断章取义地照猫画虎,对用户来说是不尊重对方,对我们来说,也只是敷衍,你对用户的不负责,怎么可能要求用户对你负责。你始终要明白,你的方案将来会有许多人去阅读,如果有人说,这是网上的照搬,或是网络方案的堆砌,那无疑给你的方案判了死刑。 14、忌只从技术的角度入手,只有技术方案,没有管理方案,要知道方案能否顺利通过验收,主要是领导层决定的。 15、一般解决方案模板 本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2011/01/04/1925931.html,如需转载请自行联系原作者
下图为JavaScript调用本地代码的通信过程 Phonegap的核心API都是基于插件的,这些JavaScript API都会调用cordova.exec() 函数来完成操作。cordova.exec()函数如下 cordova.exec(success, fail, service, action, args); 其中success是操作成功后的回调函数 fail是操作失败后的回调函数 service是所要操作的本地服务名称 action是要执行的服务的具体操作 args是操作所需要的参数 在cordova.exec() 函数中,实现JavaScript到本地代码通信的关键代码为: 1 2 3 exec: function(bridgeSecret, service, action, callbackId, argsJson) { return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId])); }, prompt函数本身为浏览器用来提示用户输入信息的。 但是实际上并没有,原因是浏览器做过处理。 在Android中,用到SystemWebChromeClient类,会覆盖WebChromeClient的onJsPrompt方法。这个函数就是用来处理JavaScrpt的prompt函数的请求 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Override public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result) { // Unlike the @JavascriptInterface bridge, this method is always called on the UI thread. String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message, defaultValue); if (handledRet != null) { result.confirm(handledRet); } else { dialogsHelper.showPrompt(message, defaultValue, new CordovaDialogsHelper.Result() { @Override public void gotResult(boolean success, String value) { if (success) { result.confirm(value); } else { result.cancel(); } } }); } return true; } 里面调用promptOnJsprompt方法 1 2 3 4 public String promptOnJsPrompt(String origin, String message, String defaultValue) { String r = jsExec(bridgeSecret, service, action, callbackId, message); ... } 在jsExec里调用 pluginManager.exec(service, action, callbackId, arguments); 至此Js到本地通信完成 参考 Android JSBridge的原理与实现 PhoneGap插件调用Java流程源码分析 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7084774.html,如需转载请自行联系原作者
1. 用命令创建cordova项目 cordova coreate hello com.example.hello hello 2.打开MainActivity 在onCreate方法中加入 setContentView(R.layout.main_activity); 3. main_activity文件如下: 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 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="45dip" android:background="#25C28B" > <ImageButton android:id="@+id/cordova_back" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="#00FFFFFF" android:paddingLeft="10dp" android:paddingRight="20dp" android:src="@drawable/back_all" /> <TextView android:id="@+id/cordova_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="原生头部" android:textColor="#FFFFFF" android:textSize="20sp" /> <Button android:id="@+id/btn_report" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="#00FFFFFF" android:paddingLeft="10dp" android:paddingRight="20dp" android:text="报告" android:textColor="#FFFFFF" android:textSize="20sp" /> </RelativeLayout> <org.apache.cordova.engine.SystemWebView android:id="@+id/cordovaWebView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> SystemWebView是一个扩展的webview 4. 重新makeWebView方法和createViews方法 1 2 3 4 5 6 @Override protected CordovaWebView makeWebView() { SystemWebView webView = (SystemWebView) findViewById(R.id.cordovaWebView); CordovaWebView cordovaWebView = new CordovaWebViewImpl(new SystemWebViewEngine(webView)); return cordovaWebView; } cordovaWebView对于xml里的SystemWebView 控件 1 2 3 4 5 6 7 8 9 10 @Override protected void createViews() { if (preferences.contains("BackgroundColor")) { int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK); // Background of activity: appView.getView().setBackgroundColor(backgroundColor); } appView.getView().requestFocusFromTouch(); } 5. 效果图 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7088821.html,如需转载请自行联系原作者
一、事件绑定 1. 创建doOnClick函数 2. 网页中绑定doOnClick方法 3. 效果图 二、 属性绑定 1. 定义imgUrl的网址 2. 定义img src属性 另外一种写法 3. html 属性绑定 在网页中绑定size 4. css html 属性绑定 html绑定 5. css增加属性 原先已经有a 和b属性, 之后增加c属性 6. ngClass管理多个css html code 1 <div [ngClass]="divClass">HI</div> 7. 样式属性 带有单位(px)的样式 1 <div [style.font-size.px]="isDev?'100':'50'">是否是开发环境</div> 8.ngStyle使用 1 <div [ngStyle]="divStyle">haha</div> divStle定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 divStyle: any = { color: 'red', background: 'yellow', }; constructor() { setTimeout(() => { this.divStyle = { color: 'yellow', background: 'red', }; }, 3000); } 另一种情况的使用 其中recListWidth是自定义的变量 三、双向绑定 html代码 app.module.ts 加入FormsModule 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7250101.html,如需转载请自行联系原作者
一、输入属性(父组件与子组件通信) 1. 创建工程 ng new demo1 2.创建order组件 ng g component order 3. 在order组件里定义输入属性 order组件的html 4. 父组件 app.component.ts中定义stock app.component.html, 采用双向绑定 效果图 最终父组件IBM的值,通过输入属性,把值传递给了子组件 二、输出属性(子组件与父组件通信) 1. ng g component priceQutoe 创建报价组件 2. 定义报价组件控制器 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 import {Component, EventEmitter, OnInit, Output} from '@angular/core'; @Component({ selector: 'app-price-quote', templateUrl: './price-quote.component.html', styleUrls: ['./price-quote.component.css'] }) export class PriceQuoteComponent implements OnInit { stockCode: string = 'IBM'; price: number; @Output('priceChange') lastPrice: EventEmitter<PriceQuote> = new EventEmitter(); constructor() { setInterval(() => { let priceQuote: PriceQuote = new PriceQuote(this.stockCode, 100 * Math.random()); this.price = priceQuote.lastPrice; this.lastPrice.emit(priceQuote); }, 1000); } ngOnInit() { } } export class PriceQuote { constructor(public stockCode: string, public lastPrice: number) { } } 3. 定义报价组件html 1 2 3 4 5 6 <p> 这里是报价组件 </p> <div> 股票代码是{{stockCode}}, 股票价格是{{price | number:'2.2-2'}} </div> 4. 父组件控制器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import { Component } from '@angular/core'; import {PriceQuote} from './price-quote/price-quote.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { stock = ''; title = 'app'; priceQuote: PriceQuote = new PriceQuote('', 0); priceQutoehandler(event: PriceQuote){ this.priceQuote = event; } } 5. 父组件html 1 2 3 4 5 6 7 8 <div> 我是父组件 </div> <app-price-quote (priceChange)="priceQutoehandler($event)"></app-price-quote> <div> 这是在报价组件外部,股票代码是{{priceQuote.stockCode}}, 股票价格是{{priceQuote.lastPrice | number:'2.2-2'}} </div> 6.效果图 三、中间人模式 当另个组件不是父子组件关系时,需要两个共同的父组件,这个父组件就是中间人模式 中间人模式同时使用了输入属性和输出属性 1. 报价组件定义 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 import {Component, EventEmitter, OnInit, Output} from '@angular/core'; @Component({ selector: 'app-price-quote', templateUrl: './price-quote.component.html', styleUrls: ['./price-quote.component.css'] }) export class PriceQuoteComponent implements OnInit { stockCode: string = 'IBM'; price: number; //@Output('priceChange') //lastPrice: EventEmitter<PriceQuote> = new EventEmitter() @Output() buy: EventEmitter<PriceQuote> = new EventEmitter(); constructor() { setInterval(() => { const priceQuote: PriceQuote = new PriceQuote(this.stockCode, 100 * Math.random()); this.price = priceQuote.lastPrice; //this.lastPrice.emit(priceQuote); }, 1000); } buyStock(event) { this.buy.emit(new PriceQuote(this.stockCode, this.price)); } ngOnInit() { } } export class PriceQuote { constructor(public stockCode: string, public lastPrice: number) { } } 2. 报价组件html 1 2 3 4 5 6 7 8 9 <p> 这里是报价组件 </p> <div> 股票代码是{{stockCode}}, 股票价格是{{price | number:'2.2-2'}} </div> <div> <input type='button' value='立即购买' (click)="buyStock($event)"> </div> 3.订单组件控制器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import {Component, Input, OnInit} from '@angular/core'; import {PriceQuote} from "../price-quote/price-quote.component"; @Component({ selector: 'app-order', templateUrl: './order.component.html', styleUrls: ['./order.component.css'] }) export class OrderComponent implements OnInit { @Input() priceQutoe: PriceQuote; constructor() { } ngOnInit() { } } 4. 订单组件html 1 2 3 4 5 6 <div> 我下单组件 </div> <div> 买100手{{priceQutoe.stockCode}}股票,买入价为{{priceQutoe.lastPrice | number:'2.2-2'}} </div> 5. 父组件的控制器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import { Component } from '@angular/core'; import {PriceQuote} from './price-quote/price-quote.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { stock = ''; priceQuote: PriceQuote = new PriceQuote('', 0); priceQutoehandler(event: PriceQuote){ this.priceQuote = event; } buyHandler(event: PriceQuote) { this.priceQuote = event; } } 6.父组件的html 1 2 3 4 5 <div> 我是父组件 </div> <app-price-quote (buy)="buyHandler($event)"></app-price-quote> <app-order [priceQutoe]="priceQuote"></app-order> 7.效果图 当点击“立即购买”时,显示当时的显示价格。 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7257929.html,如需转载请自行联系原作者
1.创建工程 ng new demo4 2. 创建子组件 ng g component child 3.子组件html定义 1 2 3 4 5 <div class="wrapper"> <h2>我是子组件</h2> <div>这个div定义在子组件中</div> <ng-content></ng-content> </div> wrapper样式定义 1 2 3 .wrapper{ background: lightgreen; } 4. 父组件html定义 1 2 3 4 5 6 7 <div class="wrapper"> <h2>我是父组件</h2> <div>这个div定义在父组件中</div> <app-child> <div>这个是父组件投影到子组件的</div> </app-child> </div> wrapper样式定义 1 2 3 .wrapper{ background: cyan; } 5.效果图 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7260380.html,如需转载请自行联系原作者
如果出现ext未定义错误,请调试导入ext的js库的顺序。 一般来说是ext的js文件的加载顺序问题。 应该为: Js代码 1. <script type="text/javascript" src="extjs/adapter/ext/ext-base-debug.js"></script> 2. <script type="text/javascript" src="extjs/ext-all-debug.js"></script> <script type="text/javascript" src="extjs/adapter/ext/ext-base-debug.js"></script> <script type="text/javascript" src="extjs/ext-all-debug.js"></script> 因为 ext 是在 ext-base.js中定义的: Js代码 收藏代码 1. Ext = { 2. /** 3. * The version of the framework 4. * @type String 5. */ 6. version : '3.0' 7. }; Ext = { /** * The version of the framework * @type String */ version : '3.0' }; 而ext-all.js的第一行 既是: Js代码 1. Ext.DomHelper = function(){ Ext.DomHelper = function(){ 直接 使用了 Ext的命名空间,所以 应该先导人定义再使用,就是顺序问题。 如果 你是用eclipse 开发的 ,上面的一切都搞定了,还是报 ext 未定义,那很可能是你的Eclipse 的缓存问题。。 即,当 基于Eclipse下的程序运行时,所运行的不是开发路径的文件,而是Eclipse编译后的文件,一般放置在你的项目名称路径下的 .metadata\.plugins \org.eclipse.wst.server.core\tmp0\wtpwebapps\你的项目名 的下面,去看一下,有时你在开发路径下导入 ext的文件,而Eclipse并没有把它编译到这个路径下。手动直接考入即可。!!! 分类: 项目有关 本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2011/12/02/2272337.html,如需转载请自行联系原作者
目录 kali Linux下wifi密码安全测试(1)虚拟机下usb无线网卡的挂载 1.1 VMWare下的配置 1.2 VirtualBox下的配置 原文链接:http://www.xuanhun521.com/Blog/2014/4/8/kali-linux%E4%B8%8Bwifi%E5%AF%86%E7%A0%81%E5%AE%89%E5%85%A8%E6%B5%8B%E8%AF%951%E8%99%9A%E6%8B%9F%E6%9C%BA%E4%B8%8Busb%E6%97%A0%E7%BA%BF%E7%BD%91%E5%8D%A1%E7%9A%84%E6%8C%82%E8%BD%BD kali Linux下wifi密码安全测试(1)虚拟机下usb无线网卡的挂载 首先我要说的是,wifi密码的破解不是想象中的那么容易,目前还没有一个可以破解任意类型wifi密码的工具或者方案存在。虽然你可以在网络上找到大量的教程,教程中有大量的成功案例,但是在实际场景中成功率是极低的。 其次,免费的午餐并不都那么好吃,希望读者在自己的内网上进行测试,毕竟学习技术是第一位的。免费午餐有可能会增加你遭受钓鱼攻击的风险。 本系列文章会针对不同安全类型的wifi网络做测试。因为我的测试都是在虚拟机中进行的,很多用户都会遇到无法获取无线网卡的问题。 必须确保你在使用USB无线网卡,虚拟机只能挂载USB无线网卡,原理我就不解释了。 启动虚拟机,在kali linux中打开终端,输入 airmon-ng 一般情况下没有任何信息,如下图: 找不到网卡,是没有办法抓包的,下面就VMWare和VirtualBox中如何加载USB无线网卡做简要的说明。 1.1 VMWare下的配置 打开VMWare,在标签页中找到虚拟机(VM),在可移动设备下找到USB 无线网卡,然后选择连接。 注意,将无线网卡连接到虚拟机,会在本机断开无线网络连接。 之后在虚拟机的右下方找到usb设备,右键,选择连接。 现在检查是否网卡挂接成功,再次输入airmon-ng命令,结果如下: 配置成功。 1.2 VirtualBox下的配置 在启动Kali Linux之前,打开虚拟机设置,选择usb设备。 点击添加设备按钮: 在设备列表中选择你的USB无线网卡。 在网络配置界面,勾选掉启用网络连接。 启动虚拟机。 在终端输入airmon-ng,可以看到加载的网卡: 同时可以在虚拟机中查找并连接无线网络了。 欢迎访问玄魂的博客 ps:对此文章或者安全、安全编程感兴趣的读者,可以加qq群:Hacking:303242737;Hacking-2群:147098303;Hacking-3群:31371755;hacking-4群:201891680;Hacking-5群:316885176 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/3651614.html,如需转载请自行联系原作者
如果在WEB服务中有这样一个场景,某个WEB服务的方法要执行两个任务,它首先要在数据库中创建一个新表,接着调用对象来收集和格式化数据,并在新表中插入数据。象这样的一组方法,我们必须保证他们都成功执行,否则会造成很多脏数据在系统中,这时事务就出场了。关于事务的基本概念再次就不过多涉及,只需要记住它的四个属性ACID即可。WEB服务中的事务是用WebMethod特性的TransactionOption属性来申明的。如果WEB服务方法执行时发生异常,则自动会终止事务,反之则提交事务。WEB服务的方法仅有两种可能的行为:Disabled,NotSupported,Supported表示不参与事务;Required,RequiresNew表示创建一个新的事务。意思是说当TransactionOption的属性为Required或RequiresNew的WEB服务方法调用另一个TransactionOption的属性为Required或RequiresNew的WEB服务方法时,每个WEB服务方法将参与他们自己的事务。PS:WEB服务方法的TransactionOption默认属性为Disabled同时我们也可以显示调用System.EnterpriseServices.ContextUtil类的SetAbort方法取消事务,调用SetCompleted方法完成事务。例子:using System.EnterpriseServices;Class WebServiceTransaction:WebService{ pulic void Write(string user,string msg) { //将接收这两个参数写入数据库。。。 } [WebMethod(TransactionOption=TransactionOption.RequiresNew)] public void WiteToDataBasev1(string user,string msg) { Write(user,msg); if(user!="kim") { string msg="sorry,you can not access"; throw new UnauthorizedAccessException(msg); } } [WebMethod(TransactionOption=TransactionOption.RequiresNew)] public void WiteToDataBaseV2(string user,string msg) { Write(user,msg); if(user!="kim") { ContextUtil.SetAbort(); } else { ContextUtil.SetComplete(); } } } 测试和预期完全正确。 本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2011/05/25/2056864.html,如需转载请自行联系原作者
问题: <asp:Repeater ID="rptList" runat="server"> <ItemTemplate> <span onclick="alert('<%=txtName.ClientID%>');">Click Me !!!</span> <input id="txtName" type="text" runat="server" /> </ItemTemplate> </asp:Repeater> 上例中 <%=txtName.ClientID%> 不正确!! ---------------------------------------------------------------------------------------------------- 答案: 1:repeater空间绑定数据有两种方式 <%= %> : 可获得.cs文件中的public 字段值,相当于Response.Write() . <%# %> :后期绑定,在指定 repeater.datasource(数据源) 属性后 ,正确语法:<%# Eval("table 中的列名") %>. 如果LZ 想让该弹窗显示迭代中每一行的 clientID 列值 应该使用第二种绑定方式. 2:<asp:Repeater ID="rptList" runat="server"> <ItemTemplate> <span onclick="alert('<%# Container.ClientID+"_txtName" %>')">click me </span> <input id="txtName" type="text" runat="server" /> </ItemTemplate> </asp:Repeater> <%# %> 这个要调用DataBind()方法 或: <asp:Repeater ID="Repeater1" runat="server"> <ItemTemplate> <span onclick="alert('<%# Container.FindControl("txtName") .ClientID%>')">click me</span> <input id="txtName" type="text" runat="server" /> </ItemTemplate> </asp:Repeater> 本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2011/07/25/2115990.html,如需转载请自行联系原作者
在程序中,常常会用到时间戳,如何生成一个时间戳呢? /// <summary> /// 获取时间戳 /// </summary> /// <returns></returns> public static string GetTimeStamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } 主要用的类:DateTime, TimeSpan 本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2011/10/17/2215692.html,如需转载请自行联系原作者
Open XML应用安全(5)数字签名 为了保证文档的完整性,防止文档被篡改,同时确保文档的来源,Open XML提供对文档进行数字签名的支持。通过使用Office文档中的签名行捕获数字签名的能力,使组织能够对合同或其他协议等文档使用无纸化签署过程。与纸质签名不同,数字签名能提供精确的签署记录,并允许在以后对签名进行验证。 创建签名 在Office中,可以通过插入签名行来来对文档进行数字签名。在“插入”选项卡中单击“签名行”,可以看到它的两个选项,如图14-28所示。 图14-28 签名行 在图14-28中,可看到三个选项,前两项是添加签名的选项,区别不大,最后一项是链接到微软的帮助页。单击Microsoft签名行,会看到如图14-29所示的“签名设置”界面。 图14-29 签名设置 设置完基本信息,单击“确定”,会看到在文档右侧关于签名的提示信息,如图14-30所示。 图14-30 尚未签署文档的提示 可以右键单击签名,单击签署,会看到如图14-31所示的签署界面。 图14-31 签署文档 在签署界面,可以选择作为签名的图像,然后单击“签名”,正式对文档进行签名。在图14-31中的颁发者中可以看到默认选择的证书,单击“更改”按钮更改用于签名的证书,如图14-32所示。 图14-32 选择证书 正式签名之后,会得到如图14-33的提示。 图14-33 签名成功提示 此时,如果尝试修改文档,会得到如图14-34的提示信息。 图14-34 已签名的文档不允许修改 那么Open XML文档是如何存储数字签名的信息呢?解压已经被签名的Word文档,一探究竟。如图14-35所示。 图14-35 查看签名后的.docx文档结构 如果细心的话,可以看到在图14-35中有一个名为_xmlsignatures的文件夹,该文件夹下的内容如图14-36所示。 图14-36 _xmlsignatures文件夹内容 图14-36中,origin.sigs文件是签名数据,用来对比文档是否被篡改;sig1.xml文件内是签名的相关信息,包括签名算法,数字证书和签名数据。文件内容较多,这里就不展示了,读者可自行查看。现在可以修改主文档中的某个文字,然后重新压缩,看看会是什么结果?如图14-37所示。 图14-37 无效签名 修改文档中的信息之后,查看签名信息,会提示无效签名。 用Open XML SDK处理签名 下面介绍如何在程序中使用Open XML SDK来处理Open XML文档的数字签名。 为了更方便地处理Open XML文档的数字签名,.NET的System.IO.Packaging名称空间提供了PackageDigitalSignatureManager类来对文档签名,获取签名信息,移除签名,验证签名。 该类包含如下10个属性: q CertificateOption。获取或设置由Sign方法使用的X.509证书嵌入选项以对包部件进行数字签名。 q DefaultHashAlgorithm。获取URI字符串,该字符串可标识用于创建和验证签名的默认哈希算法。 q HashAlgorithm。获取或设置用于创建和验证签名的 HashAlgorithm 实例的URI标识符。 q IsSigned。获取一个值,该值指示包是否包含任何签名。 q ParentWindow。获取或设置父窗口的句柄,以显示证书选择对话框。 q SignatureOrigin。获取签名源部件的URI。 q SignatureOriginRelationshipType。获取默认签名源关系的类型。 q Signatures。获取包中包含的所有签名的集合。 q TimeFormat。获取或设置用于创建签名 SigningTime 的日期/时间格式。 q TransformMapping。获取一个字典,其中包含每个定义的 ContentType 及其关联 XML Transform.Algorithm 标识符。 PackageDigitalSignatureManager类的每个方法就不一一解释了,下面来看一个实际的对Open XML包进行签名的示例。 第一个函数名为CreatePackage,其作用为创建一个Open XML包,如代码清单14-25所示。 代码清单14-25 CreatePackage函数 private static void CreatePackage(String packageFilename) { Uri uriDocument = new Uri(@"Content\Document.xml", UriKind.Relative); Uri uriResource = new Uri(@"Resources\Image1.jpg", UriKind.Relative); Uri partUriDocument = PackUriHelper.CreatePartUri(uriDocument); Uri partUriResource = PackUriHelper.CreatePartUri(uriResource); using (Package package = Package.Open(packageFilename, FileMode.Create)) { PackagePart packagePartDocument = package.CreatePart(partUriDocument, System.Net.Mime.MediaTypeNames.Text.Xml); using (FileStream fileStream = new FileStream(uriDocument.ToString(), FileMode.Open, FileAccess.Read)) { CopyStream(fileStream, packagePartDocument.GetStream()); } package.CreateRelationship(packagePartDocument.Uri, TargetMode.Internal, _samplePackageRelationshipType); PackagePart packagePartResource = package.CreatePart(partUriResource, System.Net.Mime.MediaTypeNames.Image.Jpeg); using (FileStream fileStream = new FileStream(uriResource.ToString(), FileMode.Open, FileAccess.Read)) { CopyStream(fileStream, packagePartResource.GetStream()); } packagePartDocument.CreateRelationship( new Uri(@"../Resources/Image1.jpg", UriKind.Relative), TargetMode.Internal, _sampleResourceRelationshipType); package.Flush(); SignAllParts(package); } } 在CreatePackage函数中,首先创建URI,这些URI将用于那些将要被添加到包中的部件,以及部件中的内容。然后,创建Open XML包,然后添加部件和关系,并添加了一个图片,将被用于签名。在方法的末尾调用SignAllParts方法,该方法用于执行真正的签名操作,代码如清单14-26所示。 代码清单14-26 SignAllParts函数 private static void SignAllParts(Package package) { if (package == null) throw new ArgumentNullException("SignAllParts(package)"); PackageDigitalSignatureManager dsm = new PackageDigitalSignatureManager(package); dsm.CertificateOption = CertificateEmbeddingOption.InSignaturePart; System.Collections.Generic.List<Uri> toSign = new System.Collections.Generic.List<Uri>(); foreach (PackagePart packagePart in package.GetParts()) { toSign.Add(packagePart.Uri); } toSign.Add(PackUriHelper.GetRelationshipPartUri(dsm.SignatureOrigin)); toSign.Add(dsm.SignatureOrigin); toSign.Add(PackUriHelper.GetRelationshipPartUri(new Uri("/", UriKind.RelativeOrAbsolute))); try { dsm.Sign(toSign); } catch (CryptographicException ex) { MessageBox.Show( "Cannot Sign\n" + ex.Message, "No Digital Certificates Available", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } 在SignAllParts函数中,利用传进的Package实例创建了PackageDigitalSignatureManager对象的示例dsm。设置dsm的CertificateOption属性为CertificateEmbeddingOption.InSignaturePart。随后,遍历每一个Part,取出URI,放到集合toSign中。准备工作做好以后,调用dsm.Sign(toSign)方法对每一个部件进行签名。 验证签名的有效性 下面再来看如何验证签名的有效性,先看代码清单11-27。 代码清单11-27 验证签名的有效性 private static bool ValidateSignatures(Package package) { if (package == null) throw new ArgumentNullException("ValidateSignatures(package)"); PackageDigitalSignatureManager dsm = new PackageDigitalSignatureManager(package); if (!dsm.IsSigned) return false; VerifyResult result = dsm.VerifySignatures(false); if (result != VerifyResult.Success) return false; return true; } 在代码清单11-27中,仍然使用PackageDigitalSignatureManager类验证签名的有效性,首先通过IsSigned属性来判断Open XML包是否经过签名,如果经过签名则调用VerifySignatures方法来验证签名是否有效。该方法的参数是一个bool类型,表示如果首次失败时退出,为true;如果要继续检查所有签名,则为 false。 此外也可以调用VerifyCertificate方法来验证证书是否有效。 ----------------------------注:本文部分内容改编自《.NET 安全揭秘》 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/archive/2012/06/24/2560146.html,如需转载请自行联系原作者
Python黑帽编程2.9 面向对象编程 我个人认为,计算机语言的发展,有两个方向,一个是从低到高的发展过程,在这个过程中,语言的思考和解决问题的方式是面向硬件的。硬件本质上处理的是信号,在此基础上,我们给硬件赋予了一定的“逻辑思维”能力,为了方便硬件帮我们做事,抽象出了指令的概念,进而出现了汇编语言,然后有了Pascal和C这样的标准的结构化语言。语言一路向上发展,都是根植于指令的,根植于指令就意味着流程和数据代表了一切,数据的变化成为我们表达和抽象这个世界的根本。不可否认,宇宙间的一切,都是在不停的变化中,然而命运有数,变化有法,越是着眼于变化,我们越难逃脱宿命。 在冯诺依曼的体系成为权威之前或者之后这些年中,计算机科学思考都衍生于对数学的思考。数学家认为数学语言能完美的描述这个世界,基于数学的编程语言一出来就是贵族,然而纯粹数学语言是没法用的,因为我们的机器还太低级,于是另一个编程语言的发展方向,是从数学语言向机器语言的自顶向下的发展。这其中纯粹的函数式语言是这方面的代表,比如lisp,微软的F#则是“混血”的代表。 从机器的角度理解世界,还是纯数学的方式理解世界,都不能代表人的视角和思维方式。在二者相向发展中,有了很多交汇。计算机当然离理解人的思维方式还差的很远,除非把人变成计算单元。科学家们在这个方向上努力良久,在编程语言领域“面向对象”的思想和方法被广泛接受。事物是不断变化的,人类在变化中寻找相对静止的时空来思考世界,来描述世界,文字、绘画都是语言,都需要在静止中呈现。生命尊重并表现自我,认同个体,于是世间有了物的概念。在静止中,如果还只是思考数据,那么就是混沌,观察个体才有意义,才有血肉。世间万物,物就是对象。 所谓面向对象,就是把你眼中能认为或抽象出的独立事务描述清楚,首先它是个整体,然后我们再肢解它,最后在把它重新放到变化中观察行为。抽象的越彻底,我们越能发现很多事务的共性,于是有了分类。在变化中,物与物必然会产出影响,于是有了关系。 视角发生了变化,描述事物和行为的方式必然有了变化,产生了新的表达方法,新的技巧,同时也有了新的问题和挑战,当然会产生新的解决问题的方法,这些就是面向对象的基本方法,设计模式,架构经验,等等。 扯了这么多闲篇,下面我们进入Python的面向对象世界,当然不会细致入微,简单概述为主。 2.9.1 类与对象 在python中,我们使用class关键字来定义一类事物,类是一个抽象描述,并不是真正的存在,需要把它初始化才会产生一个真正的事物,我们称之为对象。在编程过程中,拥有行为和数据的是对象,而不是类。 下面我们声明一个简单的类: #!/usr/bin/python class Person: pass # An empty block p = Person() print p 我们使用class语句后跟类名,创建了一个新的类。这后面跟着一个缩进的语句块形成类体。在这个例子中,我们使用了一个空白块,它由pass语句表示。 接下来,我们使用类名后跟一对圆括号来创建一个对象/实例。为了验证,我们简单地打印了这个变量的类型。它告诉我们我们已经在__main__模块中有了一个Person类的实例。结果如下: 图2 你可能已经注意到存储对象的计算机内存地址也打印了出来。这个地址在你的计算机上会是另外一个值,因为Python可以在任何空位存储对象。 2.9.2 对象的方法 方法代表现实世界中的行为,简单示例如下: class Person: def sayHi(self): print 'Hello, how are you?' p = Person() p.sayHi() 这里我们需要注意sayHi方法没有任何参数,但仍然在函数定义时有self,self代表对象本身,等价于C++中的self指针和Java、C#中的this引用。之后,我们通过对象名加点的方式来调用对象的方法。运行结果如下: 图3 2.9.3 构造函数 我们在使用类来构造一个对象的时候,通常在构造支出需要把对象本身的关键属性进行初始化。比如初始化一个人,如果我们认为年龄和名字是关键属性的话,我们在实例化这个人的时候,需要把相关属性的值传进来。上面我们知道出事化对象的时候是类名加括号的方式,实际上这个括号调用了一个内置的方法,我们称之为构造函数,正是该函数返回了被初始化的对象本身。 python的构造函数名为__init__,我们可以自定义传入参数的类型和个数。 #!/usr/bin/python class Person: def __init__(self, name): self.name = name def sayHi(self): print 'Hello, my name is', self.name p = Person('Swaroop') p.sayHi() 这里,我们把__init__方法定义为取一个参数name(以及普通的参数self)。在这个__init__里,我们只是创建一个新的字段 name。最重要的是,我们没有专门调用__init__方法,只是在创建一个类的新实例的时候,把参数包括在圆括号内跟在类名后面,从而传递给__init__方法。 现在,我们能够在我们的方法中使用self.name变量。这在sayHi方法中得到了验证。 图4 2.9.4 变量 变量代表属性和数据。在python中变量有两种,类变量和对象变量。类变量是全局的,对每个对象都共享,对象的变量是实例化的,每个对象之间互不影响。下面我们通过一段代码来对比: #!/usr/bin/python class Person: '''Represents a person.''' population = 0 def __init__(self, name): '''Initializes the person's data.''' self.name = name print '(Initializing %s)' % self.name # When this person is created, he/she # adds to the population Person.population += 1 def __del__(self): '''I am dying.''' print '%s says bye.' % self.name Person.population -= 1 if Person.population == 0: print 'I am the last one.' else: print 'There are still %d people left.' % Person.population def sayHi(self): '''Greeting by the person. Really, that's all it does.''' print 'Hi, my name is %s.' % self.name def howMany(self): '''Prints the current population.''' if Person.population == 1: print 'I am the only person here.' else: print 'We have %d persons here.' % Person.population swaroop = Person('Swaroop') swaroop.sayHi() swaroop.howMany() kalam = Person('Abdul Kalam') kalam.sayHi() kalam.howMany() swaroop.sayHi() swaroop.howMany() 这个例子略微有点长,但是它有助于说明类与对象的变量的本质。这里,population属于Person类,因此是一个类的变量。name变量属于对象(它使用self赋值)因此是对象的变量。 观察可以发现__init__方法用一个名字来初始化Person实例。在这个方法中,我们让population增加1,这是因为我们增加了一个人。同样可以发现,self.name的值根据每个对象指定,这表明了它作为对象的变量的本质。 在这个程序中,我们还看到docstring对于类和方法同样有用。我们可以在运行时使用Person.__doc__和Person.sayHi.__doc__来分别访问类与方法的文档字符串。 就如同__init__方法一样,还有一个特殊的方法__del__,它在对象消逝的时候被调用。对象消逝即对象不再被使用,它所占用的内存将返回给系统作它用。在这个方法里面,我们只是简单地把Person.population减1。 当对象不再被使用时,__del__方法运行,但是很难保证这个方法究竟在 什么时候 运行。如果你想要指明它的运行,你就得使用del语句,就如同我们在以前的例子中使用的那样。 这里需要注意的是: l Python中所有的类成员(包括数据成员)默认都是公有的。 l 如果你使用的数据成员名称以 双下划线前缀 比如__privatevar,Python的名称管理体系会有效地把它作为私有变量。 l 这样就有一个惯例,如果某个变量只想在类或对象中使用,就应该以单下划线前缀。而其他的名称都将作为公共的,可以被其他类/对象使用。记住这只是一个惯例,并不是Python所要求的(与双下划线前缀不同)。 l 同样,注意__del__方法与其他语言中析构函数的概念类似。 2.9.5 继承 继承这个概念,经常以父与子的关系来被阐述,我认为这阐述对初学者来说是一种误导。在人类社会中,父与子继承的是什么?是财产,实际是赠予。面向对象的继承,实际是不是从现实世界中来,而是为了解决面向对象编程的问题二产生的,要解决的是代码复用的问题。比如人类有许多共性,有鼻子,有眼睛。但是人类也是分亚种的,从肤色上划分人种,地理上划分人群。那么在定义黄种人和黑种人的时候,不可避免的要重新定义很多属性和行为,于是有了继承的概念,把公共的内容放到Person类里面,然后AsiaPerson 继承Person类,它自然就有了Person类定义的内容,这种思想,其实换个词可能更好理解——克隆。概念就不纠结了,理解就好,下面看代码: #!/usr/bin/python class SchoolMember: '''Represents any school member.''' def __init__(self, name, age): self.name = name self.age = age print '(Initialized SchoolMember: %s)' % self.name def tell(self): '''Tell my details.''' print 'Name:"%s" Age:"%s"' % (self.name, self.age), class Teacher(SchoolMember): '''Represents a teacher.''' def __init__(self, name, age, salary): SchoolMember.__init__(self, name, age) self.salary = salary print '(Initialized Teacher: %s)' % self.name def tell(self): SchoolMember.tell(self) print 'Salary: "%d"' % self.salary class Student(SchoolMember): '''Represents a student.''' def __init__(self, name, age, marks): SchoolMember.__init__(self, name, age) self.marks = marks print '(Initialized Student: %s)' % self.name def tell(self): SchoolMember.tell(self) print 'Marks: "%d"' % self.marks t = Teacher('Mrs. Shrividya', 40, 30000) s = Student('Swaroop', 22, 75) print # prints a blank line members = [t, s] for member in members: member.tell() # works for both Teachers and Students 为了使用继承,我们把基类的名称作为一个元组跟在定义类时的类名称之后。然后,我们注意到基类的__init__方法专门使用self变量调用,这样我们就可以初始化对象的基类部分。这一点十分重要——Python不会自动调用基类的构造函数。调用基类的构造函数需要使用基类名进行调用,而且传入子类的self。 注意,在我们使用SchoolMember类的tell方法的时候,我们把Teacher和Student的实例仅仅作为SchoolMember的实例。 另外,在这个例子中,我们调用了子类型的tell方法,而不是SchoolMember类的tell方法。可以这样来理解,Python总是首先查找对应类型的方法,在这个例子中就是如此。如果它不能在导出类中找到对应的方法,它才开始到基本类中逐个查找。 python支持多继承,可以同时继承多个基类。 2.9.6 小结 Python是一个高度面向对象的语言,我们只是过了一些基本概念,万物皆对象的理念,也让高级的python编程变得更加有趣。 下一节开始,我们进入黑帽编程的阶段,先来讨论主机到网络层典型攻击。 第3.0节《网络接口层攻击基础知识》已经在微信订阅号抢先发布,心急的同学进入订阅号(二维码在下方),从菜单“网络安全”—>”Python黑帽编程”进入即可。 查看完整系列教程,请关注我的微信订阅号(xuanhun521,下方二维码),回复“python”。问题讨论请加qq群:Hacking (1群):303242737 Hacking (2群):147098303。 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/5776586.html,如需转载请自行联系原作者
首先说明,本周活动有效时间为2016年10月11日到2016年10月16日。本周为大家送出的书是由电子工业出版社出版,鬼脚七著《做自己-鬼脚七自媒体第一季》。 鬼脚七 何许人也?当然不是电影黄飞鸿里的鬼脚七了,当年是大淘宝搜索技术的核心人物,目前人居何职,我也不是很清楚,哈哈。目前它的微信订阅号也是 自媒体圈子里面鼎鼎大号。这本书是他几年前的文章合集,介绍了作者对人生,对淘宝,对阿里,对做生意等各个方面的感悟。 我也关注了鬼脚七的自媒体, 现在和他当年的这本书对比来看,干货越来越少,更新频率也慢了,内容也更玄乎了。 目录 · · · · · · 第一篇关于生活 2 做自己 002号 4 勇敢向上,坚决向左 007号 6 关于无常 008号 8 谈出发点 014号 10 两个故事 018号 12 回家 019号 13 借假修真 020号 15 我们还能专注吗 023号 17 如何超越时间 027号 20 不要让时间支配了你 031号 24 小感动 032号 26 世界上最远的距离 039号 30 关于情绪 044号 33 提问的原则 047号 37 提问的智慧 048号 39 放下与爱情 049号 43 知易行难 050号 46 空杯和学习 055号 50 如果还有明天 058号 54 玩游戏的思考 059号 56 我们是一群乌合之众 066号 60 莫言:悠着点,慢着点 a5号第二篇关于互联网 62 快和慢 005号 64 什么是中小微企业 011号 66 是谁在阻碍我们创新 022号 70 《是谁在阻碍我们创新》文章背后的故事 022号 73 用互联网的方式做公司 028号 77 关于产品经理的四点思考 036号 83 发生在每个人身边的商业案例 038号 88 降级论 052号 94 小偷的故事 056号 98 该觉醒的互联网产品经理 060号 102 慢公司和小而美 060号 106 小即是美——2012年度网商发展研究报告 a2号 106 我们理解的网络、搜索、计算机都将消失 a3号 107 战胜免费 a13号 107 张小龙:微信产品观(上/下) b2号 108 周鸿祎:像怀胎一样怀产品 b3号第三篇关于自媒体 110 关于孤独 001号 112 自媒体广告,卖的是未来 017号 116 管理员工:有人用梦想,有人用麻将 030号 120 自媒体广告,到底值多少钱 041号 127 自媒体人,你能走多远 045号 131 不能错过的那些文章(上) 046号 137 不能错过的那些文章(下) 046号 144 自媒体价值探讨之#微任务# 053号 148 支援雅安!鬼脚七广告开放三天 062号 150 鬼脚七关于卖广告的回应 063号 153 鬼脚七——第一季即将结束 064号 156 一个自媒体人的内心独白 068号第四篇关于淘宝 162 关于苦——和一个年销售额5000万的卖家的对话 003号 165 无变化,不阿里 006号 167 一个淘宝卖家如何做到10%订单来自微信 009号 171 由白菜价引起的思考 013号 174 我接触的马云 024号 177 一个淘宝卖家交税的故事 029号 181 《一个淘宝卖家交税的故事》背后的故事 029号 183 淘宝客服的那些事 034号 193 淘宝客服的那些事(2) 034号 203 淘宝客服的那些事(3) 034号 214 关于淘宝直通车的那些事 040号 221 关于淘宝直通车的那些事(二) 040号 232 关于淘宝直通车的那些事(三) 040号 237 关于淘宝直通车的那些事(四) 040号 246 如果时间有背景,你会不会一直仰望042号 251 从《我是歌手》学淘宝运营(上) 054号 256 从《我是歌手》学淘宝运营(下) 054号 262 运营是门艺术 065号 266 淘宝卖家如何玩转微信 b1号 269 马云演讲:永远不要放弃梦想(2009.11) 026号 269 2005年6月9日:《对话》狂人马云a1号 270 2013年2月3日:《对话马云》 a1号 271 马云:面对腾讯和阿里,该如何创业 033号 273 马云最新演讲:不要去证明你的模式是对的 035号 275 逍遥子:天猫的2013 a9号 275 马云:时间会证明一切(上/下) a10号第五篇关于搜索 277 鬼脚七在北京网商年会上的演讲 004号 279 淘宝搜索的2012(上) 010号 283 淘宝搜索的2012(下) 010号 287 卖家如何应对淘宝搜索新功能 012号 291 搜索的悖论 015号 293 淘宝卖家应该知道的搜索知识(上)016号 296 淘宝卖家应该知道的搜索知识(下)016号 299 如何做淘宝搜索标题优化 021号 304 如何做淘宝搜索标题优化(续) 021号 309 鬼脚七2013年3月在搜索学院上的演讲 025号 318 淘宝常见问题及鬼脚七的回答(1)037号 324 淘宝新店应该修炼的9大内功 051号 331 你不知道的淘宝搜索功能 057号 337 鬼脚七回答淘宝搜索问题 067号 341 淘宝搜索优化之道(2010.10) a7号尾声 346 相聚和离别(第一季大结局) 069号 351 「第一季•做自己」经典语录 070号 下面关键来了,如果你心动了,如何得到本书呢? 1.在微信订阅号对应的本篇文章下面留言,谈谈你对互联网,生活,生命的认识,理解,感悟或者有趣的故事和想法 2.让你的朋友帮助给你的留言点赞 3.如果你的感悟或者故事很精彩,可以投稿给我们。 评选标准: 1.点赞数最高的留言者,会获得本书 2.如果你有和本书内容相关的投稿,如果被采纳,在订阅号发布,本书优先奖励给你。 3.同时有多人投稿的话,回到第1条。 微信扫描下发二维码,关注订阅号,回复“每周一书”,了解最新的运行情况,最近的送书小活动,获取书籍的方法都在文章里面。 每周一书,总有一本是你喜欢的。 玄魂工作室-做最好的自己 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/5949710.html,如需转载请自行联系原作者
本文来自 高海峰对 玄魂工作室 的投稿 作者:高海峰 QQ:543589796 在渗透测试的初步阶段通常我们都需要对攻击目标进行信息搜集,而端口扫描就是信息搜集中至关重要的一个步骤。通过端口扫描我们可以了解到目标主机都开放了哪些服务,甚至能根据服务猜测可能存在某些漏洞。 TCP端口扫描一般分为以下几种类型: TCP connect扫描:也称为全连接扫描,这种方式直接连接到目标端口,完成了TCP三次握手的过程,这种方式扫描结果比较准确,但速度比较慢而且可轻易被目标系统检测到。 TCP SYN扫描:也称为半开放扫描,这种方式将发送一个SYN包,启动一个TCP会话,并等待目标响应数据包。如果收到的是一个RST包,则表明端口是关闭的,而如果收到的是一个SYN/ACK包,则表示相应的端口是打开的。 Tcp FIN扫描:这种方式发送一个表示拆除一个活动的TCP连接的FIN包,让对方关闭连接。如果收到了一个RST包,则表明相应的端口是关闭的。 TCP XMAS扫描:这种方式通过发送PSH、FIN、URG、和TCP标志位被设为1的数据包。如果收到了一个RST包,则表明相应的端口是关闭的。 下面我们将使用Python3 实现TCP全连接端口扫描器,下面进入编程环节。 编码实战 全连接扫描方式的核心就是针对不同端口进行TCP连接,根据是否连接成功来判断端口是否打开,现在我们来实现一个最简单的端口扫描器: #!/usr/bin/python3 # -*- coding: utf-8 -*- from socket import * def portScanner(host,port): try: s = socket(AF_INET,SOCK_STREAM) s.connect((host,port)) print('[+] %d open' % port) s.close() except: print('[-] %d close' % port) def main(): setdefaulttimeout(1) for p in range(1,1024): portScanner('192.168.0.100',p) if __name__ == '__main__': main() 这段代码的核心就是portScanner函数,从其中的内容可以看出,只是进行了简单的TCP连接,如果连接成功则判断为端口打开,否则视为关闭。 我们来看一下运行结果: 这样的扫描看起来效率太低了,实际也确实很慢,因为我们设置了默认的超时时间为1秒,这要是扫描10000个端口,岂不是要等到花都谢了? 最简单的办法就是用多线程来提高效率,虽然python的多线程有点太弱了,不过至少可以利用我们等待的时间去干点别的。另外之前扫描的端口比较多, 显示的信息我们看起来不方便,这次我们只显示我们关心的打开的端口,并将打开端口的数量在扫描结束的时候显示出来。 #!/usr/bin/python3 # -*- coding: utf-8 -*- from socket import * import threading lock = threading.Lock() openNum = 0 threads = [] def portScanner(host,port): global openNum try: s = socket(AF_INET,SOCK_STREAM) s.connect((host,port)) lock.acquire() openNum+=1 print('[+] %d open' % port) lock.release() s.close() except: pass def main(): setdefaulttimeout(1) for p in range(1,1024): t = threading.Thread(target=portScanner,args=('192.168.0.100',p)) threads.append(t) t.start() for t in threads: t.join() print('[*] The scan is complete!') print('[*] A total of %d open port ' % (openNum)) if __name__ == '__main__': main() 运行看一下效果,如下图: 这下看起来是不是方便多了?至此效率上的问题解决了,现在我们还需要为扫描器增加一个 参数解析的功能,这样才能看起来像个样子,总不能每次都改代码来修改扫描目标和端口吧! 参数解析我们将用python3自带的标准模块argparse,这样我们就省去了自己解析字符串的麻烦! 下面来看代码: #!/usr/bin/python3 # -*- coding: utf-8 -*- from socket import * import threading import argparse lock = threading.Lock() openNum = 0 threads = [] def portScanner(host,port): global openNum try: s = socket(AF_INET,SOCK_STREAM) s.connect((host,port)) lock.acquire() openNum+=1 print('[+] %d open' % port) lock.release() s.close() except: pass def main(): p = argparse.ArgumentParser(description='Port scanner!.') p.add_argument('-H', dest='hosts', type=str) args = p.parse_args() hostList = args.hosts.split(',') setdefaulttimeout(1) for host in hostList: print('Scanning the host:%s......' % (host)) for p in range(1,1024): t = threading.Thread(target=portScanner,args=(host,p)) threads.append(t) t.start() for t in threads: t.join() print('[*] The host:%s scan is complete!' % (host)) print('[*] A total of %d open port ' % (openNum)) if __name__ == '__main__': main() 看一下运行效果,如下图: 至此我们的端口扫描器就基本完成了,虽然功能比较简单,旨在表达端口扫描器的基本实现思路! 至于更详细的功能可以基于这个基本结构来逐步完善! 小结 本节主要讲解了Python3实现一个简单的端口扫描器的过程,本次实验采用了Tcp全连接的方式,不断尝试连接主机的端口来判断端口的开放情况,虽然存在一些缺点, 不过这种方式最适合初学者学习,至于更复杂的方式以后学习起来也不会很难。想举一反三的朋友可以根据协议和端口的对照关系来完成扫描时同时输出协议, 这样看起来会更好一些,至于更详细的功能就留给大家做练习了! 查看完整系列教程,请关注我的微信订阅号(xuanhun521,下方二维码),回复“python”。问题讨论请加qq群:Hacking (1群):303242737 Hacking (2群):147098303。 玄魂工作室-精彩不断 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/5950433.html,如需转载请自行联系原作者
Python黑帽编程 4.0 网络互连层攻击概述 是时候重新温习下下面这张图了。 图2 本章的内容核心包含上图中的网络层和传输层。TCP/IP是整个网络协议体系中的核心,因为从这里开始,数据传输从局域网迈向了广阔的互联网,我们的程序也有能力处理来自互联网的数据,可以直接对互联网上的主机进行攻击和测试。 还是老话,希望各位深入的学习协议,通过抓包工具练习数据包分析,通过实例理解协议。下面我们把本章涉及到的内容做简略的描述。 4.0.1 嗅探与嗅探器原理 嗅探是一个综合概念,涉及到我们之前讲到的第二层一直到未来要讲到的应用层。数据嗅探是被动攻击的一种方式,它通过分析流经本机网卡的数据,来提取需要的信息。 根据不同的网络类型,我们可能要结合ARP欺骗/DNS欺骗这样方式,才能得到我们想要的目标主机的数据。 嗅探器就是用来获取和分析数据的的工具了,网络上有很多这样的工具,我们的关注点是这些工具的原理和编码实现。 4.0.2 IP毒化攻击和洪水攻击 之前降到的ARP毒化攻击类似, IP毒化就是构造假的IP数据包,使用假的IP地址,来达到攻击或者隐藏自己是目的。 在这一层,我们可以构造各种数据包对互联网上的设备进行洪水攻击,比如常用是SYN洪水,各种协议的连接洪水攻击等。 4.0.3 端口扫描和服务探测 zmap,nmap是我们常用的端口扫描和服务探测程序。我们也知道端口扫描有很多不同的实现技术,从简单的全连接到半开连接。据说一个小时可以扫描整个互联网的zmap,它又使用了什么先进的技术呢?我会在文章中为你一一揭秘。 4.0.4 会话劫持 “劫持”是一个非常重要的概念,只有截断数据的流向,我们才能有机会进行篡改数据,伪造正常的会话。常见的会话的目标都是应用层的数据概念,但是进行劫持都是在传输层来做的。我们将会看到如何通过编程来实现会话劫持和数据篡改的实际例子。 4.0.5 拒绝服务攻击 DOS或者DDOS,我们都不陌生,但是拒绝服务的概念在不同场景下的解释还是不一样的,基于网络和传输层的拒绝服务攻击是什么样的呢?又是如何实现的呢? 利用DTP协议攻击Cisco设备,本节的方法需要和3.4节的方法结合使用。 第4.1节《嗅探器入门》已经在微信订阅号抢先发布,心急的同学进入订阅号(二维码在下方),从菜单“专栏”—>”Python黑帽编程”进入即可。 查看完整系列教程,请关注我的微信订阅号(xuanhun521,下方二维码),回复“python”。问题讨论请加qq群:Hacking (1群):303242737 Hacking (2群):147098303。 玄魂工作室-精彩不断 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/5957536.html,如需转载请自行联系原作者
Python黑帽编程 3.5 DTP攻击 在上一节,《Python黑帽编程 3.4 跨越VLAN》中,我们讨论了一般的VLAN中实施攻击的方法,这一节属于扩展内容,简单演示下Cisco特有的DTP协议的攻击方法。 由于条件限制,本节的代码我没有在实际环境下测试,不保证有效,欢迎讨论。 3.5.1 DTP协议 动态中继协议 DTP(Dynamic Trunking Protocol)是一种 Cisco 私有协议。DTP 用于两台交换机的直连二层端口探测对端的配置,自动协商出二层端口的链路类型和以太协议封装进而与对端自适应。这样当对端设备修改时,就不用手工修改本端配置,通过协议自适应更改即可。DTP 的重要作用是,在组网不确定的情况下,可以实现即插即用;修改网络拓扑时,也不用手工修改二层端口的配置。 DTP 利用第二层中继帧,在两台交换机的直连端口之间进行通信。DTP 报文仅限于两个 直连端口之间的通信,维护两个直连端口的链路类型和以太封装类型。工作原理如图2所示。 图2 如果交换机开启了DTP协议,攻击者假冒交换机向目标交换机发送Dynamic desirable数据包,那么会把目标端口变成Trunking端口,这意味着我们可以通过修改本机的配置进入任何一个VLAN,同时可以利用3.4节的方法进行VLAN跳跃攻击,监听所有数据了。 3.5.2 发送DYNAMIC DESIRABLE数据包 在Scapy的scapy.contrib.dtp包中有一个negotiate_trunk方法,原型如下: def negotiate_trunk(iface=conf.iface, mymac=str(RandMAC())): print "Trying to negotiate a trunk on interface %s" % iface p = Dot3(src=mymac, dst="01:00:0c:cc:cc:cc")/LLC()/SNAP()/DTP(tlvlist=[DTPDomain(),DTPStatus(),DTPType(),DTPNeighbor(neighbor=mymac)]) sendp(p) 该方法第一个参数需要我们传入发送数据包的网卡,第二个是可选参数,可以用来传入要假冒的交换机的Mac地址,如果不传入,会随机产生一个。 调用该方法,就可以完成Dynamic desirable数据包的生成和发送工作。如下代码所示: 图3 数据包发送之后,会有一些延迟才会生效。 3.5.3 小结 本节主要讲了如何利用DTP协议攻击Cisco设备,本节的方法需要和3.4节的方法结合使用。 下一节,我们进入第四章《网络层攻击》。 第4.0节《网络层攻击概述》已经在微信订阅号抢先发布,心急的同学进入订阅号(二维码在下方),从菜单“专栏”—>”Python黑帽编程”进入即可。 查看完整系列教程,请关注我的微信订阅号(xuanhun521,下方二维码),回复“python”。问题讨论请加qq群:Hacking (1群):303242737 Hacking (2群):147098303。 玄魂工作室-精彩不断 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/5914516.html,如需转载请自行联系原作者
作者:玄魂工作室 \ 2016年10月20日 把Kali Linux安装到U盘好处很多,可以从U盘启动使用整个电脑的硬件资源, 可以随身携带,减少对自己电脑的影响。 今天要给大家讲的是如何在windows上安装Kali Linux到U盘上的方法。首先, 我们准备基本的材料: 一个至少8G的U盘 到Kali Linux官网下载最新的ISO映像文件(https://www.kali.org/downloads/) 软件Universal USB Installer(订阅号 回复 "usb",获取下载地址) 虚拟机Vmware 1.1 制作U盘启动盘 准备好基本物料之后,我们打开 USB Installer。 在Step1下选择要安装的操作系统类型为 Kali Linux。 在Step2下选择Kali Linux的ISO文件的磁盘路径。 在Step3下选择要写入的Upan,是否格式化根据情况选择。 点击按钮“Create”。 警告框显示要进行的操作,再检查一遍,如果没有问题,点击按钮“是”即可。 安装完成后,关闭窗口即可. 下面我们重新启动电脑,设置从U盘启动。 这个是还可以使用Live模式进行操作了,也可以选择Live Persistence 模式,就可以放心的使用Kali了。 很多人到这一步之后还想继续安装,可能会卡在这里,几个典型的错误, 我说一下: 如果你没有事先做好分区,系统是安装不能这个U盘上的,因为系统文件都在这里,你没有办法重新分区,不过可以插另一个U盘,然后选择它 作为要安装系统的介质进行安装。 可能会遇到挂载不到光盘的错误,只需要拔出U盘,重新插入即可。 其他安装的东西和正常安装的步骤是一样的,可以参考我之前的文章 Python黑帽编程1.1虚拟机安装和配置 Kali Linux 2016 1.2 使用Vmware安装系统到U盘 其实在windows上,我们有更为方便的办法,就是使用Vmware虚拟机,因为虚拟机对我们这个群体来讲, 几乎是必备的软件。下面我们看看如何利用Vmware把Kali 安装到U盘中。 开始之前先确认一下Vmware的Usb服务是否开启,如果非运行状态请开启之。 然后新建虚拟机,详细过程略,请参考Python黑帽编程1.1虚拟机安装和配置 Kali Linux 2016。 选择从光盘映像安装系统。 虚拟机名称,内存,网络,IO控制器,虚拟磁盘类型,创建磁盘的地方,都随意配置就行了。这些 配置都没什么用处。完成之后,先不要启动虚拟机,查看虚拟机的硬件配置,移除虚拟磁盘。 然后再手动添加硬盘。 在选择设备的时候要注意,如何知道U盘是哪个设备呢?需要从计算机的磁盘管理界面查看。 完成之后,确认一下信息。 启动虚拟机,进入安装阶段,参考Python黑帽编程1.1虚拟机安装和配置 Kali Linux 2016。 玄魂工作室-精彩不断 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/5981984.html,如需转载请自行联系原作者
双11临近,玄魂工作室 准备在 11月10,11,12 三天在微信订阅号,做些小活动。 活动期间会各种方式,为大家送出由我们自己编写的教程,合作伙伴提供的资料。 对外发放的教程和资料清单,会陆续在微信订阅号发出。 此次放出的是 赞助商 为玄魂工作室 双十一提供的第一批物料。这些书都是玄魂本人亲自挑选的,而且都读过,个人感觉值得送给大家。 Kali Linux高级渗透测试 [加] 罗伯特 W.贝格斯(Robert,W.,Beggs) 著;蒋溢 译 京东售价:48.7 KaliLinux面向专业的渗透测试和安全审计,集成了大量精心挑选的安全检测工具。本书在KaliLinux平台上从一个攻击者的角度来审视网络框架,详细介绍了攻击者“杀链”采取的具体步骤。通过阅读本书读者能快速学习和掌握渗透测试方法和工具。 安全技术经典译丛:SQL注入攻击与防御(第2版) [SQL Injection Attacks and Defense,Second Edition] 京东售价:50.8 SQL注入攻击是一种已经长期存在,但近年来日益增长的安全威胁,《安全技术经典译丛:SQL注入攻击与防御(第2版)》致力于深入探讨SQL注入问题。 《安全技术经典译丛:SQL注入攻击与防御(第2版)》前一版荣获2009Bejtlich图书奖,第2版对内容做了全面更新,融入了一些的研究成果,包括如何在移动设备上利用SQL注入漏洞,以及客户端SQL注入等。 《安全技术经典译丛:SQL注入攻击与防御(第2版)》由一批SQL注入专家编写,他们对Oracle、SQLServer、MySQL和PostgreSQL数据库平台的SQL注入问题具有独到的见解。 主要内容: ·发现、确认和自动发现SQL注入漏洞 ·通过SQL注入利用漏洞 ·在代码中发现SQL注入的方法和技巧 ·利用操作系统的漏洞 ·在代码层和平台层防御SQL注入攻击 ·确定是否已经遭到SQL注入攻击 黑客大曝光:无线网络安全(原书第3版) 资深无线网络安全专家撰写,既包含当前常用网络的各种技术,也包含新型的无线技术的入侵,是利用和防御较新无线网络攻击的学习指南 [美] 乔舒亚·莱特(Joshua Wright)约翰 著;李瑞民 译 京东售价:81.7 本书系统介绍如何通过详尽的信息安全知识,保护无线系统免受瘫痪式的攻击,全面更新和囊括了当今已广泛使用和新兴的无线技术,揭示攻击者如何利用既有的或者定制的黑客工具来锁定、渗透并攻击系统,帮助读者更好地维护无线网络安全。全书共分为三部分,一部分专门讨论针对Wi-Fi的破解技术,第二部分主要介绍蓝牙网络的破解,第三部分介绍的是除了Wi-Fi协议和蓝牙协议之外,其他无所不在的网络无线技术及其所支持的网络。 本书主要内容: 装备一套针对无线网络攻击的利器工具包,熟练掌握黑客的武器。 有效地扫描Wi-Fi网络,列举和评估该网络上的所有客户端设备。 使用先进的无线攻击工具,包括:集众长于一身的Wifite工具、“框架类”的程序Scapy工具、WPA-PSK认证进行暴力破解Pyrit工具、开源的漏洞检测Metasploit工具、专攻ZigBee网络的KillerBee工具,以及黑客必备的Aircrack-ng工具套件。 通过“ARP欺骗”和数据包转发的Ettercap工具和“Wi-Fi小菠萝”破解并发起基于客户端的攻击。 使用GSM信号探测器Airprobe工具、GSM数据包捕获和解密工具Kraken、GSM加密数据破解工具Pytacle和实施“中间人”攻击的YateBTS工具入侵手机网络。 在目前广泛使用的基于WPA和WPA2认证加密的个人或企业安全方案的网络中,寻找和突破漏洞。 使用“骗子”AP接入点,通过虚假的软件升级传送远程访问控制软件。 在“传统蓝牙模式”和“低功耗蓝牙模式”的网络中,侦测传送的数据包。 通过“软件无线收发”工具捕获和评估专有的无线技术。 在使用ZigBee和Z-Wave网络技术连接的智能家居和工业办公室网络中,探索网络中存在的漏洞。 使用一台已被攻陷的Windows操作系统主机,使用内置的工具,对一个远程无线网络实施攻击。 黑客攻防技术宝典 Web实战篇第2版 网络安全必知!异类黑客入门必备宝典,黑客攻防从入门到精通实用手册!安全技术宝典全新升级! [英] 斯图塔德(Stuttard D.)著;石华耀,傅志红 译 京东售价:69.8 《黑客攻防技术宝典.Web实战篇(第2版)》是探索和研究Web 应用程序安全漏洞的实践指南。作者利用大量的实际案例和示例代码,详细介绍了各类Web 应用程序的弱点,并深入阐述了如何针对Web 应用程序进行具体的渗透测试。本书从介绍当前Web 应用程序安全概况开始,重点讨论渗透测试时使用的详细步骤和技巧,总结书中涵盖的主题。每章后还附有习题,便于读者巩固所学内容。 第2 版新增了Web 应用程序安全领域近年来的发展变化新情况,并以尝试访问的链接形式提供了几百个互动式“漏洞实验室”,便于读者迅速掌握各种攻防知识与技能。 《黑客攻防技术宝典.Web实战篇(第2版)》适合各层次计算机安全人士和Web 开发与管理领域的技术人员阅读。 汇编语言:基于Linux环境(第3版) [Assembly Language] [美] 达特曼(Jeff Duntemann)著;梁晓晖 译 京东售价:82.1 Python 黑帽子:黑客与渗透测试编程之道 安全畅销书《Python灰帽子》同作者姊妹篇知道创宇余弦、腾讯胡珀及Keen、蓝莲花等知名黑客战队联合作序盛赞 京东价:43.4 本书是畅销书《Python 灰帽子―黑客与逆向工程师的 Python 编程之道》的姊妹篇,那本书一面市便占据计算机安全类书籍的头把交椅。本书由 Immunity 公司的高级安全研究员 Justin Seitz 精心撰写。作者根据自己在安全界,特别是渗透测试领域的几十年经验,向读者介绍了 Python 如何被用在黑客和渗透测试的各个领域,从基本的网络扫描到数据包捕获,从 Web 爬虫到编写 Burp 扩展工具,从编写木马到权限提升等。作者在本书中的很多实例都非常具有创新和启发意义,如 HTTP 数据中的图片检测、基于 GitHub命令进行控制的模块化木马、浏览器的中间人攻击技术、利用 COM 组件自动化技术窃取数据、通过进程监视和代码插入实现权限提升、通过向虚拟机内存快照中插入 shellcode 实现木马驻留和权限提升等。通过对这些技术的学习,读者不仅能掌握各种 Python 库的应用和编程技术,还能拓宽视野,培养和锻炼自己的黑客思维。读者在阅读本书时也完全感觉不到其他一些技术书籍常见的枯燥和乏味。 Wireshark数据包分析实战(第2版) [美] Chris Sanders 著;诸葛建伟,陈霖,许伟林 译 京东价:42.7 《Wireshark数据包分析实战(第2版)》从网络嗅探与数据包分析的基础知识开始,渐进地介绍Wireshark的基本使用方法及其数据包分析功能特性,同时还介绍了针对不同协议层与无线网络的具体实践技术与经验技巧。在此过程中,作者结合一些简单易懂的实际网络案例,图文并茂地演示使用Wireshark进行数据包分析的技术方法,使读者能够顺着本书思路逐步地掌握网络数据包嗅探与分析技能。最后,《Wireshark数据包分析实战(第2版)》使用网络管理员、IT技术支持、应用程序开发者们经常遇到的实际网络问题(包括无法正常上网、程序连接数据库错误、网速很卡,以及遭遇扫描渗透、ARP欺骗攻击等),来讲解如何应用Wireshark数据包分析技术和技巧,快速定位故障点,并找出原因以解决实际问题。 图解密码技术第3版 易懂的密码学畅销书全面升级新增椭圆曲线密码比特币等前沿内容 [日] 结城浩 著;周自恒 译 京东价:71.8 本书以图配文的形式,详细讲解了6种重要的密码技术:对称密码、公钥密码、单向散列函数、消息认证码、数字签名和伪随机数生成器。 第1部分讲述了密码技术的历史沿革、对称密码、分组密码模式(包括ECB、CBC、CFB、OFB、CTR)、公钥密码、混合密码系统。第2部分重点介绍了认证方面的内容,涉及单向散列函数、消息认证码、数字签名、证书等。第3部分讲述了密钥、随机数、PGP、SSL/TLS 以及密码技术在现实生活中的应用。第3版对旧版内容进行了大幅更新,并新增POODLE攻击、心脏出血漏洞、Superfish事件、SHA-3竞赛、Keccak、认证加密、椭圆曲线密码、比特币等内容。 网络分析技术揭秘:原理、实践与WinPcap深入解析 以WinPcap的源码分析为依托,深刻阐释了网络分析技术的方法、原理和实践 吕雪峰 等著 京东价:67.1 《网络分析技术揭秘:原理、实践与WinPcap深入解析》结合著名的开源软件库WinPcap来说明网络分析技术的实现原理及使用方法。其中包括WinPcap内核驱动,编译与使用,数据包的捕获、发送、内核过滤与接收,以及网络流量的统计与网络状态的分析等重要内容,而且作者还通过修改内核级的源代码解决了开源代码本身尚未完成的一个重要功能—数据包的内核转储。经过系统深入的分析,读者既能对WinPcap的架构、使用与实现机制有深入的理解,又能快速熟悉操作系统内核与用户层交互的实现机制,并全面了解网络分析专业各方面的技术,进而将相关知识运用到实际项目中。如果您的工作与网络软件相关,无论是开发人员还是测试人员,我们都强烈建议您阅读这本书。 逆向工程实战 [美] 邓(Bruce Dang),[法] 加泽(Alexandre Gazet),[美] 巴沙拉尼(Elias Bachaalany),[法] 若斯(Sébastien Josse)著;单业 译 京东价:50.2 本书是一本涵盖x86、x64 和ARM 操作系统的逆向工程类图书,由浅入深地讲解了包括Windows内核模式代码的恶意软件和驱动程序、虚拟机保护技术等内容。作者通过大量真实案例和示例,提供了系统化的解决方案。本书适合所有程序员和想要开始学习逆向工程的读者阅读。 最后,欢迎更多组织和机构赞助我们的活动。玄魂工作室的粉丝并不多,但是大家都有相同的兴趣和爱好,任何形式的合作或支持,都本着发扬原创、公益精神,为站在网络安全|编程|互联网的地面上的小伙伴们打起加油! 活动具体参与方式会在11月9号发送,锁定我们的订阅号,不抛弃,不放弃! 玄魂工作室---精彩不断 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/5984860.html,如需转载请自行联系原作者
Python黑帽编程 4.1 Sniffer(嗅探器)之数据捕获(上) 网络嗅探,是监听流经本机网卡数据包的一种技术,嗅探器就是利用这种技术进行数据捕获和分析的软件。 编写嗅探器,捕获数据是前置功能,数据分析要建立在捕获的基础上。本节就数据捕获的基本原理和编程实现做详细的阐述。 4.1.1 以太网网卡的工作模式 以太网网卡是我们日常生活中见得最多的网卡,我们的电脑通过网线或者wifi接入网络,使用的都是以太网网卡。 图2 常用的以太网卡支持以下工作模式:广播模式、多播模式、直接模式和混杂模式。 1.广播模式(Broad Cast Model):它的物理地址(MAC)地址是 0Xffffff 的帧为广播帧,工作在广播模式的网卡接收广播帧。它将会接收所有目的地址为广播地址的数据包,一般所有的网卡都会设置为这个模式。 2.多播传送(MultiCast Model):多播传送地址作为目的物理地址的帧可以被组内的其它主机同时接收,而组外主机却接收不到。但是,如果将网卡设置为多播传送模式,它可以接收所有的多播传送帧,而不论它是不是组内成员。当数据包的目的地址为多播地址,而且网卡地址是属于那个多播地址所代表的多播组时,网卡将接纳此数据包,即使一个网卡并不是一个多播组的成员,程序也可以将网卡设置为多播模式而接收那些多播的数据包。 3.直接模式(Direct Model):工作在直接模式下的网卡只接收目地址是自己Mac地址的帧。只有当数据包的目的地址为网卡自己的地址时,网卡才接收它。 4.混杂模式(Promiscuous Model):工作在混杂模式下的网卡接收所有的流过网卡的帧,信包捕获程序就是在这种模式下运行的。网卡的缺省工作模式包含广播模式和直接模式,即它只接收广播帧和发给自己的帧。如果采用混杂模式,网卡将接受同一网络内所有主机发送的数据包。 利用网卡混杂模式的特性,就可以到达对于网络信息监听捕获的目的。 需要注意的是,并不是任何情况下,网络中的数据都会流经你的网卡,比如交换机网络,交换机会绑定端口和MAC,此时就需要上一章讲到的ARP欺骗了。 4.1.2 设置网卡为混杂模式 在Kali Linux中,我们可以通过ifconfig和iwconfig配置网络接口的信息。 正常情况下输入ifconfig,虚拟机中显示如下: 图3 通过命令 ifconfig eth0 promisc 可以将eth0设置为混杂模式。 图4 图四中圈红的部分,表示当前网卡处于混杂模式。 通过ifconfig eth0 -promisc 可以取消网卡的混杂模式。 图5 ifconfig同样适用于无线网卡。 4.1.3 无线网卡的监听模式 对于无线网卡,我们可以使用iwconfig的mode参数来配置混杂模式,mode的选项值如下: 1) Ad-hoc:不带AP的点对点无线网络 2) Managed:通过多个AP组成的网络,无线设备可以在这个网络中漫游 3) Master:设置该无线网卡为一个AP 4) Repeater:设置为无线网络中继设备,可以转发网络包 5) Secondary:设置为备份的AP/Repeater 6) Monitor:监听模式 7) Auto:由无线网卡自动选择工作模式 使用如下命令可以设置无线网卡为监听模式: ifconfig wlan0 down iwconfig wlan0 mode monitor ifconfig wlan0 up 在Kali中我们通过iwconfig来设置混杂模式,可能会遇到点困难,无线网卡设置成混杂模式后,过几秒又变成manage模式了。这是由于Network Manage服务造成,我们可以关闭该服务。 监听模式和上文的混杂模式有什么区别呢?混杂模式是在wifi连接到指定网络中,监听子网中的数据传输;监听模式下wifi会断网,进而监听某一个信道内所有传输流量,因此可以用来扫描wifi热点,破解wifi密码等工作。 下面我们来看一下如何编程实现Sniffer。 4.1.4 可以在WINDOWS上运行的SNIFFER Raw Socket是一种较为底层的socket编程接口,可以用来获取IP层以上的数据,所以可以用来编写Sniffer。一个完整的sniffer代码组成,大致分为创建socket对象,接收数据,分析数据三个部分。其中开启网卡的混杂模式,需要配置socket对象的属性。在开启混杂模式方面,Linux上要比windows上复杂一点,我们先从简单的情况开始。 首先我们定义出程序的基本框架。 在上面的代码中,我们首先定义了一个类——PromiscuousSocket,这个类负责创建一个绑定到当前主机名绑定的网卡上的raw socket对象,并设置启动混杂模式。PromiscuousSocket类有三个方法,分别为类的构造函数,另外两个函数是用于with关键字的块作用域的起止函数,不了解的同学请翻阅Python的编程基础资料看一下。sniffer函数会创建PromiscuousSocket类的实例,并使用它接收和分析数据。printPacket方法用来显示捕获的数据内容。 接下来我们来完善核心的PromiscuousSocket类,在__init__方法中,我们创建socket对象,并绑定到对象的s字段上。 def __init__(self): #创建socket HOST = socket.gethostbyname(socket.gethostname()) s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((HOST, 0)) s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) self.s = s 这段代码首先创建一个socket对象,第一个字段family我们选择ipv4;第二个字段type,选择raw socket。(这里关于socket编程的基础内容,如果你不是很理解,可以先看一看本教程的2.8节。) setsockopt函数是用来对socket对象进行补充选项的设置,三个参数的分别为level、选项名称和值。 level支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。 可用的socket层选项名字如下: 协议层 选项名字SOL_SOCKET SO_REUSEADDRSOL_SOCKET SO_KKEPALIVESOL_SOCKET SO_LINGERSOL_SOCKET SO_BROADCASTSOL_SOCKET SO_OOBINLINESOL_SOCKET SO_SNDBUFSOL_SOCKET SO_RCVBUFSOL_SOCKET SO_TYPESOL_SOCKET SO_ERROR 代码中我们使用了SOL_SOCKET 的SO_REUSEADDR 选项,该选项可以让多个socket对象绑定到相同的地址和端口上。 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 设置了该选项之后,我们调用bind方法,来绑定socket。 s.bind((HOST, 0)) 接下来我们再次通过setsockopt函数来设置数据保护IP头部。 s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 最后,通过ioctl函数类设置混杂模式,注意传入的两个参数,第一个指定设置的类型为接收所有数据,第二个参数要个第一个对应,使用RCVALL_ON来开启。 s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 我们再来看完善的__enter__函数。 def __enter__(self): return self.s 代码很简单,返回创建的socket对象。 __exit__方法中,我们调用ioctl方法通过RCVALL_OFF来关闭混杂模式。代码如下: def __exit__(self, *args, **kwargs): self.s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) 完善的sniff方法如下: def sniffer(count, bufferSize=65565, showPort=False, showRawData=False): with PromiscuousSocket() as s: for i in range(count): # receive a package package = s.recvfrom(bufferSize) printPacket(package, showPort, showRawData) sniff方法利用PromiscuousSocket的一个实例,接收数据包,然后调用printPacket方法打印基本信息。 def printPacket(package, showPort, showRawData): dataIndex = 0 headerIndex = 1 ipAddressIndex = 0 portIndex = 1 print('IP:', package[headerIndex][ipAddressIndex], end=' ') if(showPort): print('Port:', package[headerIndex][portIndex], end=' ') print('') #newline if(showRawData): print('Data:', package[dataIndex]) printPacket方法接收数据包对象,打印对应信息。这里不用过多解释,传入的package对象作为二维数组被解析,通过调试可以知道数据包里面的内容,从而进一步调整程序。 4.1.5 解决LINUX上混杂模式问题 至此,一个简单 的嗅探程序就完成了,在windows上可以运行无误了。不过在linux上会遇到问题,在设置混杂模式的代码: s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) Python并没有将SIO_RCVALL和RCVALL_ON及RCVALL_OFF暴露出来。但是系统底层的C结构体是有这样的定义的,这里我们通过fcntl模块的fcntl对象的ioctl方法来配置选项。这里面涉及一个Python编程中python对象和C 类型转换的知识点,我这里就不展开了,不太知道的同学请自行查找资料解决。 这里我们先将要用到的数值封装到类FLAGS中。 class FLAGS(object): # linux/if_ether.h ETH_P_ALL = 0x0003 # 所有协议 ETH_P_IP = 0x0800 # 只处理IP层 # linux/if.h,混杂模式 IFF_PROMISC = 0x100 # linux/sockios.h SIOCGIFFLAGS = 0x8913 # 获取标记值 SIOCSIFFLAGS = 0x8914 # 设置标记值 然后创建一个ifreq类,如下: class ifreq(ctypes.Structure): _fields_ = [("ifr_ifrn", ctypes.c_char * 16), ("ifr_flags", ctypes.c_short)] 该类继承自ctypes.Structure类,使用它我们可以通过字符串中转c结构体字段的值。 下面我们看如何使用FLAGS和ifreq类。 在PromiscuousSocket类初始化socket的代码部分,我们增加下面的代码。 if os.name == 'posix': import fcntl # posix-only s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(FLAGS.ETH_P_ALL)) ifr = ifreq() ifr.ifr_ifrn = b'eth0' #此处注意,这里写死了网卡名称,需要根据实际情况修改或者传入 fcntl.ioctl(s, FLAGS.SIOCGIFFLAGS, ifr) # 获取标记字段的名称 ifr.ifr_flags |= FLAGS.IFF_PROMISC # 添加混杂模式的值 fcntl.ioctl(s, FLAGS.SIOCSIFFLAGS, ifr) # 更新 self.ifr = ifr 上面的代码中,注意几个地方。htons方法用来将16bit的正数的字节顺序转换为网络传输的顺序(所谓的大端,小端,不了解的请google之)。我们创建了一个ifreq类的实例 ifr,接下来设置绑定的网卡的名字,这里程序写死了,需要根据实际情况调整。通过 fcntl.ioctl(s, FLAGS.SIOCGIFFLAGS, ifr) # 获取标记字段的名称 将当前socket已经有的Flag获取到,然后加上设置混杂模式的数值,在通过 fcntl.ioctl(s, FLAGS.SIOCSIFFLAGS, ifr) # 更新 更新给socket对象,从而使该socket具有获取所有数据的能力。 在__exit__方法中,取消混杂模式的代码我们也要修改一下: def __exit__(self, *args, **kwargs): if os.name == 'posix': import fcntl self.ifr.ifr_flags ^= FLAGS.IFF_PROMISC fcntl.ioctl(self.s, FLAGS.SIOCSIFFLAGS, self.ifr) else: self.s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) 这段代码就不必再解释了,根据上面的说明应该看得明白。 4.1.6 小结 到此为止,我们基于raw socket实现的嗅探器就完成了,实现我们捕获数据的目的。此种方法,需要大家对操作系统本身对网络协议栈的描述,有较为深入的理解。下一节,我们让这个过程变得轻松一点,使用一些流行的网络库来实现Sniffer。 第4.2节《4.1 Sniffer(嗅探器)之数据捕获(下)》已经在微信订阅号抢先发布,心急的同学进入订阅号(二维码在下方),从菜单“专栏”—>”Python黑帽编程”进入即可。 查看完整系列教程,请关注我的微信订阅号(xuanhun521,下方二维码),回复“python”。问题讨论请加qq群:Hacking (1群):303242737 Hacking (2群):147098303。 玄魂工作室-精彩不断 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/5994126.html,如需转载请自行联系原作者
本周为大家送出的书是《Oracle 12 c PL(SQL)程序设计终极指南》,此书由机械工业出版社出版, 孙风栋,王澜,郭晓惠 著。 内容简介: 《Oracle 12c PL/SQL程序设计终极指南》志在打造PL/SQL领域最为系统、全面、实战、权威的著作,通过一系列非常突出的优势在大量的同类书中脱颖而出,成为该领域的标准读物。 PL/SQL本身涉及的知识点浩瀚、庞杂,初学者根本无法依靠自身能力理清头绪,学习成本极高。本书对知识点进行了体系化的梳理,化繁杂为有序,突出重点,直指核心,循序渐进,尽可能为学习者提供“捷径”。仅仅只是这一点,本书就与同类书拉开了距离。本书以Oracle的最新版本12c为基础,呈现的是最新的PL/SQL技术,这一点也优于已出版的同类书。全书以一个综合性的人力资源项目为驱动,不仅能将各个理论知识点很好地融入实践,而且还能让读者体验完整的项目实操过程,“精讲多练”也是本书的一个重要特色,确保读者真正能学会。当然,最为重要的还是内容本身,本书首先对PL/SQL的理论基础进行了全面的介绍,其次详细讲解PL/SQL开发的所有功能模块、方法和技巧,最后对它的各种高级特性也进行了深入探讨。 国内关于PL/SQL的书很多,但是像本书这样以PL/SQL的最新版本为基础,以实际的项目为驱动,系统、全面、深入地讲解PL/SQL的书应该极少。本书旨在为所有初学者和工作中的Oracle数据库工程师提供关于PL/SQL的“终极参考”。 《Oracle 12c PL/SQL程序设计终极指南》具有下列特色: 项目驱动,侧重实战:全书以一个人力资管理系统开发为主线,根据项目开发的实际过程、实际需要介绍PL/SQL程序设计方法、技术、技巧,案例详实,包含了大量的代码与图例。 内容全面,注重实效:全书既介绍了PL/SQL基础知识和PL/SQL基本开发技术,供PL/SQL的初学者学习,也介绍了PL/SQL高级特性,供有一定开发经验的读者学习。全书强调“精讲多练”,压缩了不必要的理论介绍,侧重实际开发技术的训练,核心技术来源于实际应用与Oracle官方文档。读者也可以把本书作为参考手册进行查阅。 深入浅出,结构合理:全书按照PL/SQL程序设计的实际需要进行组织,分基础篇、开发篇、高级篇三篇。基础篇介绍了PL/SQL程序设计的基础知识,包括基本语法、控制结构、游标、异常处理等;开发篇介绍了PL/SQL程序最实用的开发技术,包括子程序、包、触发器、动态SQL、批绑定、子程序依赖性等;高级篇介绍了Oracle对象、LOB大对象、作业调度管理、性能优化以及PL/SQL内置包等高级特性。 推陈出新,技术先进:全书将Oracle 12c PL/SQL的最新特性融入整个知识体系,包括以调用者权限执行的函数可以进行结果缓存、更多的PL/SQL独有数据类型可以与SQL进行交互、使用ACCESSIBLE BY 短语进行访问控制、使用FETCH FIRST短语实现TOP-N查询、将角色授予PL/SQL包和独立子程序,等等。 目录 前言 基础篇 第1章 PL/SQL概述 1.1 什么是PL/SQL 1.2 PL/SQL优点 1.3 PL/SQL特性 1.4 PL/SQL运行机制 1.4.1 PL/SQL引擎 1.4.2 PL/SQL单元与编译参数 1.5 PL/SQL 12.1新特性 1.6 案例数据库介绍 1.6.1 案例数据库表与序列 1.6.2 创建表与序列 1.6.3 向表中插入数据 1.7 使用Oracle文档 1.8 小结 第2章 PL/SQL开发工具的使用 2.1 SQL Plus 2.1.1 SQL Plus简介 2.1.2 SQL Plus的启动与退出 2.1.3 SQL Plus常用命令 2.2 SQL Developer 2.2.1 SQL Developer简介 2.2.2 创建数据库连接 2.2.3 浏览与管理数据库对象 2.2.4 执行SQL语句 2.2.5 开发PL/SQL程序 2.2.6 执行与调试PL/SQL程序 2.3 PL/SQL Developer 2.3.1 PL/SQL Developer简介 2.3.2 连接数据库 2.3.3 编写与运行PL/SQL程序 2.3.4 测试PL/SQL程序 2.4 小结 第3章 PL/SQL基础 3.1 PL/SQL程序结构 3.1.1 PL/SQL块结构 3.1.2 PL/SQL块分类 3.2 PL/SQL词法单元 3.2.1 字符集 3.3.2 标识符 3.2.3 分隔符 3.2.4 字面值 3.2.5 注释 3.3 PL/SQL数据类型 3.3.1 PL/SQL数据类型概述 3.3.2 字符类型 3.3.3 数字类型 3.3.4 日期/时间类型 3.3.5 布尔类型 3.3.6 复合类型 3.3.7 引用类型 3.3.8 LOB类型 3.3.9 %TYPE属性 3.3.10 %ROWTYPE属性 3.4 PL/SQL变量与常量 3.4.1 常量与变量的声明 3.4.2 变量作用域与可见性 3.5 运算符与表达式 3.5.1 运算符 3.5.2 表达式 3.6 编译指示 3.7 小结 第4章 PL/SQL控制语句 4.1 条件选择语句 4.1.1 IF语句 4.1.2 CASE语句 4.2 循环语句 4.2.1 简单循环语句 4.2.2 WHILE循环语句 4.2.3 FOR循环语句 4.2.4 CONTINUE语句 4.3 顺序控制语句 4.3.1 GOTO语句 4.3.2 NULL语句 4.4 小结 第5章 数据查询 5.1 SQL语言概述 5.1.1 SQL语言介绍 5.1.2 SQL语言的分类 5.1.3 SQL语言的特点 5.2 SELECT语句基本语法 5.3 简单查询 5.3.1 无条件查询 5.3.2 有条件查询 5.4 查询排序 5.5 分组查询 5.5.1 常用的聚集函数 5.5.2 分组查询的语法 5.5.3 单列分组查询 5.5.4 多列分组查询 5.5.5 使用HAVING子句 5.5.6 使用ROLLUP 和CUBE子句 5.5.7 合并分组查询 5.6 连接查询 5.6.1 笛卡尔积连接 5.6.2 内连接 5.6.3 自然连接 5.6.4 使用USING子句的连接 5.6.5 外连接 5.7 子查询 5.7.1 子查询概述 5.7.2 单行单列子查询 5.7.3 多行单列子查询 5.7.4 单行多列子查询 5.7.5 多行多列子查询 5.7.6 相关子查询 5.7.7 在FROM子句中使用子查询 5.7.8 在DDL语句中使用子查询 5.7.9 使用WITH子句的子查询 5.8 层次查询 5.8.1 层次结构的概念 5.8.2 层次查询的语法 5.8.3 层次查询的执行过程 5.8.4 层次查询相关伪列 5.9 集合查询 5.9.1 UNION 5.9.2 UNION ALL 5.9.3 INTERSECT 5.9.4 MINUS 5.10 分析查询 5.10.1 分析查询概述 5.10.2 分析查询的语法 5.10.3 分析函数的应用 5.11 TOP-N与分页查询 5.11.1 Oracle 12c之前的TOP-N与分页查询 5.11.2 Oracle 12c中的TOP-N与分页查询 5.12 小结 第6章 数据操纵与事务控制 6.1 数据插入 6.1.1 数据插入介绍 6.1.2 INSERT语句的语法 6.1.3 插入单行记录 6.1.4 使用子查询插入数据 6.1.5 使用Direct-Path方法插入数据 6.1.6 无条件多表插入 6.1.7 有条件多表插入 6.2 数据修改 6.2.1 UPDATE语句的语法 6.2.2 使用子查询修改数据 6.3 MERGE语句 6.4 数据删除 6.4.1 DELETE语句的语法 6.4.2 使用子查询删除数据 6.4.3 使用TRUNCATE清除数据 6.5 事务控制 6.5.1 事务概述 6.5.2 Oracle事务的隔离级别 6.5.3 使用SET TRANSACTION语句设置事务 6.5.4 事务提交与回滚 6.6 锁 6.6.1 Oracle数据库中锁的分类 6.6.2 Oracle数据库中的DML锁 6.6.3 使用LOCK TABLE语句 6.7 小结 第7章 内置SQL函数 7.1 内置SQL函数概述 7.2 单行函数 7.2.1 数字函数 7.2.2 字符函数 7.2.3 日期函数 7.2.4 转换函数 7.2.5 空值函数 7.2.6 其他单行函数 7.3 聚集函数 7.4 分析函数 7.5 其他函数 7.6 小结 第8章 PL/SQL中的静态SQL语句 8.1 静态SQL语句概述 8.1.1 静态SQL语句类型 8.1.2 PL/SQL中的SELECT语句 8.1.3 PL/SQL中的DML语句 8.1.4 PL/SQL中的字符匹配 8.2 显式游标 8.2.1 游标概述 8.2.2 声明与定义显式游标 8.2.3 打开与关闭显式游标 8.2.4 检索显式游标 8.2.5 显式游标的属性 8.2.6 显式游标定义中的变量 8.2.7 参数化显式游标 8.2.8 FOR UPDATE游标 8.3 隐式游标 8.3.1 隐式游标介绍 8.3.2 隐式游标的属性 8.4 游标变量 8.4.1 游标变量简介 8.4.2 声明游标变量 8.4.3 打开与关闭游标变量 8.4.4 检索游标变量 8.5 游标表达式 8.6 自治事务 8.6.1 自治事务的概念 8.6.2 声明自治程序 8.6.3 自治事务的控制 8.6.4 自治触发器 8.7 小结 第9章 记录 9.1 记录类型概述 9.2 声明记录类型 9.3 记录类型变量 9.3.1 声明记录类型变量 9.3.2 利用%ROWTYPE声明记录类型变量 9.3.3 记录类型变量赋值 9.4 记录类型变量的应用 9.4.1 记录类型变量在SELECT语句中的应用 9.4.2 记录类型变量在INSERT语句中的应用 9.4.3 记录类型变量在UPDATE语句中的应用 9.4.4 DML语句中记录类型变量使用的限制 9.5 小结 第10章 错误处理 10.1 编译警告 10.2 异常处理概述 10.2.1 Oracle错误处理机制 10.2.2 使用异常处理的优点 10.3 异常的类型 10.3.1 预定义异常 10.3.2 内部定义异常 10.3.3 用户定义异常 10.4 抛出异常 10.4.1 用户定义异常的抛出 10.4.2 预定义异常的抛出 10.4.3 内部定义异常的抛出 10.4.4 重新抛出当前异常 10.4.5 RAISE_APPLICATION_ERROR方法的使用 10.5 捕获与处理异常 10.5.1 异常处理器 10.5.2 OTHERS异常处理器 10.6 异常的传播 10.6.1 执行部分异常的传播 10.6.2 声明部分与异常处理部分异常的传播 10.7 异常处理策略 10.7.1 异常处理的基本原则 10.7.2 异常的范围 10.7.3 避免未处理的异常 10.7.4 异常与事务 10.7.5 错误位置标识 10.8 小结 开发篇 第11章 PL/SQL子程序 11.1 PL/SQL子程序概述 11.1.1 PL/SQL子程序的概念与分类 11.1.2 PL/SQL子程序的优点 11.2 独立子程序 11.2.1 子程序结构 11.2.2 创建存储过程 11.2.3 创建函数 11.3 调用子程序 11.3.1 调用存储过程 11.3.2 在PL/SQL程序中调用函数 11.3.3 在SQL语句中调用函数 11.4 子程序参数 11.4.1 形式参数与实际参数 11.4.2 参数的传递方式 11.4.3 参数模式 11.4.4 NOCOPY关键字 11.4.5 参数的约束 11.4.6 IN模式参数默认值 11.4.7 无参子程序 11.4.8 实参与形参的对应关系 11.5 嵌套子程序 11.5.1 嵌套子程序的概念 11.5.2 嵌套子程序的创建 11.5.3 嵌套子程序的向前声明 11.5.4 嵌套子程序的重载 11.6 独立子程序的管理 11.7 小结 第12章 PL/SQL包 12.1 包概述 12.1.1 包的概念 12.1.2 包的分类 12.1.3 使用包的优点 12.2 创建包 12.2.1 包规范 12.2.2 包体 12.3 调用包 12.4 重载包 12.5 实例化与初始化包 12.6 包的纯度等级 12.7 包的状态 12.7.1 变量持续性 12.7.2 游标持续性 12.7.3 SERIALLY_REUSABLE包 12.8 包编写指南 12.9 STANDARD包 12.10 包管理 12.11 小结 第13章 子程序依赖性与权限管理 13.1 对象依赖性概述 13.1.1 对象依赖性的概念 13.1.2 对象依赖关系查询 13.2 子程序的本地依赖性 13.2.1 子程序的依赖关系 13.2.2 包的依赖性关系 13.3 子程序的远程依赖性 13.3.1 远程依赖关系的建立 13.3.2 远程依赖失效的识别 13.4 子程序权限概述 13.4.1 子程序调用需要的权限 13.4.2 子程序定义者需要的权限 13.5 调用者权限与定义者权限 13.6 小结 第14章 触发器 14.1 触发器简介 14.1.1 触发器的概念 14.1.2 触发器的作用 14.1.3 触发器的种类 14.1.4 触发器的结构 14.2 简单的DML触发器 14.2.1 简单DML触发器概述 14.2.2 语句级简单DML触发器 14.2.3 行级简单DML触发器 14.2.4 简单DML触发器的执行顺序 14.3 INSTEAD OF DML触发器 14.3.1 INSTEAD OF DML触发器概述 14.3.2 创建INSTEAD OF DML触发器 14.3.3 基于视图嵌套表列的INST-EAD OF DML触发器 14.4 复合DML触发器 14.4.1 复合DML触发器概述 14.4.2 创建复合DML触发器 14.4.3 复合DML触发器应用 14.5 利用DML触发器保证引用完整性 14.6 系统触发器 14.6.1 系统触发器的响应事件 14.6.2 创建系统触发器 14.6.3 事件属性函数 14.7 变异表触发器 14.7.1 变异表触发器的限制 14.7.2 变异表触发器应用 14.8 触发器设计指南 14.9 触发器管理 14.9.1 触发器定义的限制 14.9.2 触发器的禁用与激活 14.9.3 触发器的修改、重编译与删除 14.9.4 触发器的信息查询 14.10 小结 第15章 集合 15.1 集合概述 15.2 联合数组 15.2.1 联合数组概述 15.2.2 定义联合数组 15.2.3 操作联合数组 15.3 嵌套表 15.3.1 嵌套表概述 15.3.2 定义嵌套表 15.3.3 初始化嵌套表 15.3.4 操作嵌套表 15.4 可变数组 15.4.1 可变数组概述 15.4.2 可变数组的定义与初始化 15.4.3 操作可变数组 15.5 集合方法 15.6 集合类型变量的比较 15.6.1 集合类型变量与NULL的比较 15.6.2 嵌套表变量比较 15.6.3 嵌套表变量多集合条件比较 15.7 独立集合类型 15.7.1 嵌套表在数据库中的应用 15.7.2 可变数组在数据库中的应用 15.8 在包中定义的集合类型 15.9 多维集合 15.10 小结 第16章 动态SQL语句 16.1 动态SQL语句概述 16.1.1 动态SQL语句的概念 16.1.2 动态SQL语句与静态SQL语句的比较 16.2 本地动态SQL 16.2.1 EXECUTE IMMEDIATE语句 16.2.2 动态DDL操作 16.2.3 动态DCL操作 16.2.4 动态DML操作 16.2.5 动态单行查询操作 16.2.6 动态多行查询操作 16.2.7 在动态SQL语句中调用子程序 16.2.8 动态SQL语句中的重名占位符 16.3 DBMS_SQL包 16.3.1 DBMS_SQL包概述 16.3.2 DBMS_SQL包中方法介绍 16.3.3 DBMS_SQL操作流程 16.3.4 使用DBMS_SQL包执行动态DDL语句 16.3.5 使用DBMS_SQL包进行动态DML语句 16.3.6 使用DBMS_SQL包执行动态查询语句 16.3.7 使用DBMS_SQL包执行匿名块 16.3.8 其他常用DBMS_SQL方法应用 16.4 小结 第17章 批绑定 17.1 批绑定概述 17.2 FORALL语句 17.2.1 FORALL语句的语法 17.2.2 FORALL语句与FOR LOOP语句比较 17.2.3 批量DML操作 17.2.4 使用稀疏集合的FORALL语句 17.2.5 FORALL语句的异常处理 17.2.6 获取FORALL语句影响的记录数量 17.3 BULK COLLECT短语 17.3.1 SELECT BULK COLLECT语句 17.3.2 FETCH BULK COLLECT语句 17.3.3 RETURNING BULK COLLECT短语 17.4 动态批绑定 17.4.1 动态批量DML操作 17.4.2 动态批查询操作 17.5 小结 高级篇 第18章 对象 18.1 Oracle对象概述 18.1.1 Oracle对象简介 18.1.2 使用Oracle对象的优势 18.1.3 Oracle数据库的对象特性 18.2 对象类型定义 18.2.1 对象类型规范 18.2.2 对象类型体 18.3 对象类型方法 18.3.1 MEMBER方法 18.3.2 STATIC方法 18.3.3 MAP与ORDER方法 18.3.4 构造方法 18.4 对象类型的继承 18.4.1 对象类型继承概述 18.4.2 FINAL与NOT FINAL对象类型与方法 18.4.3 创建子对象类型 18.4.4 方法重定义与重载 18.4.5 NOT INSTANTIABLE对象类型与方法 18.5 操作数据库中对象 18.5.1 创建对象表 18.5.2 操作对象表 18.5.3 操作列对象 18.5.4 对象引用 18.6 对象视图 18.6.1 对象视图概述 18.6.2 创建对象视图 18.6.3 在对象视图中嵌套对象 18.6.4 操作对象视图 18.7 在PL/SQL中使用对象类型 18.7.1 对象的声明与初始化 18.7.2 操作PL/SQL中的对象 18.8 与对象相关的函数和操作符 18.9 对象类型的管理 18.9.1 修改对象类型 18.9.2 删除对象类型 18.10 小结 第19章 大对象 19.1 大对象概述 19.1.1 为什么使用大对象 19.1.2 LOB与LONG的比较 19.1.3 LOB分类 19.1.4 LOB存储结构与定位器 19.1.5 LOB操作技术与接口 19.2 利用SQL操纵LOB对象 19.2.1 创建包含LOB列的数据库表 19.2.2 利用SQL操作内部LOB 19.2.3 利用SQL操作外部LOB 19.3 DBMS_LOB包 19.3.1 DBMS_LOB包简介 19.3.2 DBMS_LOB包中子程序介绍 19.4 利用PL/SQL操纵LOB对象 19.4.1 利用DBMS_LOB包操作CLOB对象 19.4.2 利用DBMS_LOB包操作BLOB对象 19.4.3 利用DBMS_LOB包操作BFILE对象 19.5 小结 第20章 Oracle任务调度 20.1 Oracle调度器概述 20.1.1 Oracle调度器的概念 20.1.2 调度对象 20.2 作业对象管理 20.2.1 创建作业对象 20.2.2 修改作业对象 20.2.3 运行作业对象 20.2.4 停止作业对象 20.2.5 删除作业对象 20.2.6 禁用作业对象 20.2.7 激活作业对象 20.3 程序对象管理 20.4 调度对象管理 20.5 小结 第21章 PL/SQL性能优化 21.1 PL/SQL性能优化简介 21.2 子程序内联 21.3 SQL语句优化 21.3.1 SQL语句优化概述 21.3.2 SQL语句执行过程 21.3.3 将常用程序驻留内存 21.3.4 有效使用索引 21.3.5 采用适当的多表连接技术 21.3.6 SQL语句使用技巧 21.4 最小化CPU载荷 21.4.1 优化查询中的函数调用 21.4.2 优化子程序调用 21.4.3 优化循环 21.4.4 优化用于计算的PL/SQL代码 21.4.5 使用SQL字符函数 21.4.6 批SQL与批绑定 21.5 管道函数的使用 21.5.1 表函数概述 21.5.2 创建管道表函数 21.5.3 管道表函数作为转换函数 21.5.4 检索管道表函数的返回结果集 21.5.5 向管道表函数传递游标表达式 21.6 性能优化工具 21.6.1 使用Profiler API工具 21.6.2 使用Trace API工具 21.6.3 使用PL/SQL hierarchical profiler工具 21.7 小结 第22章 常用的Oracle内置包 22.1 Oracle内置包简介 22.2 DBMS_ALERT包 22.3 DBMS_DDL包 22.4 DBMS_FLASHBACK包 22.5 DBMS_METADATA包 22.5.1 DBMS_METADATA包简介 22.5.2 DBMS_METADATA包中子程序 22.6 DBMS_LOGMNR包 22.7 DBMS_LOGMNR_D包 22.8 DBMS_PIPE包 22.8.1 Oracle管道通信概述 22.8.2 DBMS_PIPE包中子程序 22.9 DBMS_RANDOM包 22.10 DBMS_ROWID包 22.11 DBMS_TRANSACTION包 22.12 UTL_FILE包 22.13 UTL_TCP包 22.14 小结 获取方法 如果你心动了,如何得到本书呢? 1.如果你此时不在微信内,请进入微信订阅号(xuanhun521),回复“每周一书”,找到对应的本篇文章,在下面留言,谈谈你对数据库,oracle的认识,理解,感悟或者有趣的故事和想法 2.让你的朋友帮助给你的留言点赞 3.如果你的感悟或者故事很精彩,可以投稿给我们。 评选标准: 1.点赞数最高的,或者留言非常精彩的留言者,会获得本书 2.如果你有和本书内容相关的投稿,如果被采纳,在订阅号发布,本书优先奖励给你。 3.同时有多人投稿的话,回到第1条。 微信扫描下发二维码,关注订阅号,回复“每周一书”,了解最新的运行情况,最近的送书小活动,获取书籍的方法都在文章里面。 每周一书,总有一本是你喜欢的。 玄魂工作室-用知识搭建沟通的桥梁 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6015350.html,如需转载请自行联系原作者
Visual Studio Code 使用Git进行版本控制 本来认为此类教程,肯定是满网飞了。今天首次使用VS Code的Git功能,翻遍了 所有中文教程,竟没有一个靠谱的。遂动笔写一篇。 请确保你安装了最新的VS Code.http://code.visualstudio.com/ 请确保安装了最新版的Git。https://git-scm.com/download。git安装到环境变量里, 确保任意路径可以访问。 参考链接:https://code.visualstudio.com/Docs/editor/versioncontrol VS Code 集成了Git功能,并支持基本的git命令,这使得我们能够在开发过程方便的提交和获取代码。 1.1 初始化 首先我们创建一个名为gittest的文件夹,当然它不在git的版本控制管理中。 用VS Code 打开这个文件夹,单击左侧的git图标。 我们可以看到“初始化GIT存储库”的按钮,单击。 初始化之后,我们首先看到的是git栏里显示了当前所有文件,有4个更改。 全部或者单个文件都可以选择暂存或者清理掉。 在上方有提交和刷新按钮,下拉菜单里有更多选项。 再回到我们的文件中,刚才的操作创建了一个.git文件夹,放置了当前仓库的所有 配置文件,如下图。 到目前为止我们在本地创建了一个代码仓库,下面来看一下VS Code的git功能。 git 输出 我们可以在隐藏的菜单中选择git输出,这样我们每个操作都会显示 在输出区域,方便我们查看对应的git命令。 提交保存 提交保存的第一步是暂存文件。 第二步是输入提交信息。 第三步然后使用状态栏的提交按钮提交全部更改。 git命令列表 ctrl+shift+P,输入git,会看到VS CODE支持的所有git命令。 撤销操作 输入 Undo Last Commit,撤销上次操作。输入Unstage,撤销暂存。 分支 输入Branch可以创建当前内容的分支。创建分支时需要输入分支名称。 checkout 创建分支后,使用checkout命令可以拉取特定的分支内容。 冲突合并 VS Code 会检测文件冲突,并以<<<<<,>>>>,====和颜色区分出来。 解决冲突之后,直接提交就行了。 文件比较 在git文件列表中,单击一个未提交更改的文件,就会打开两个窗口来显示变更的内容。 连接远程代码仓库 说了这么多,现在问题来了,在本机初始化一个代码库,一般没什么卵用。 我们大多数情况是要连接远程的代码服务器的。 下面我们在github上创建一个Repository,复制地址备用。 接下来到当前Repository文件夹根目录中,如果没有初始化过,安装文章开始初始化的方法,进行初始化。 然后执行下面的命令 git remote add origin https://github.com/xuanhun/vscode.git git pull origin master 现在我们查看一下.git文件夹下的config文件,可以看到添加了远程Reps地址。 接下来我们从下拉菜单中执行发布命令。 这时会提醒我们输入账号和密码。 输入之后,会把本地提交的文件同步到github。同步之后再打开git的隐藏菜单,可以看到 同步等命令可以直接使用了。 简化一点的方法 当然我们也可以使用git 的clone命令,从远程克隆一个Reps,然后直接用vscode打开文件夹, VS Code 会自动识别各项配置。 持久化账号 远程连接git的问题解决了,如果你不想每次同步的时候都输入账号信息,可以全局存储账号, 解决这个问题。 git config --global credential.helper wincred 小结 本文的大部分内容都能从官方的文档上找到,不过中文很多教程没有解决连接远程 服务的问题,所以特地做了说明,希望对各位有所帮助。 最后,本篇文章作为实验内容,同步到github的地址为: VS Code 集成git 更多精彩内容,关注玄魂工作室微信订阅号: 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6019038.html,如需转载请自行联系原作者
目录 语言无关类 操作系统 智能系统 分布式系统 编译原理 函数式概念 计算机图形学 WEB服务器 版本控制 编辑器 NoSQL PostgreSQL MySQL 管理和监控 项目相关 设计模式 Web 大数据 编程艺术 其它 语言相关类 Android APP AWK C/C++ C# Clojure CSS/HTML Dart Elixir Erlang Fortran Go Groovy Haskell iOS Java JavaScript LaTeX LISP Lua OCaml Perl PHP Prolog Python R Ruby Rust Scala Shell Swift 读书笔记及其它 测试相关 语言无关类 操作系统 Debian参考手册 开源世界旅行手册 鸟哥的Linux私房菜 The Linux Command Line (中英文版) Linux 设备驱动 (第三版) 深入分析Linux内核源码 UNIX TOOLBOX Docker中文指南 Docker —— 从入门到实践 Docker入门实战 Docker Cheat Sheet FreeRADIUS新手入门 Mac 开发配置手册 FreeBSD 使用手册 Linux 命令行(中文版) Linux 构建指南 Linux工具快速教程 Linux Documentation (中文版) 嵌入式 Linux 知识库 (eLinux.org 中文版) 理解Linux进程 命令行的艺术 SystemTap新手指南 操作系统思考 智能系统 一步步搭建物联网系统 分布式系统 走向分布式 编译原理 《计算机程序的结构和解释》公开课 翻译项目 函数式概念 傻瓜函数编程 计算机图形学 OpenGL 教程 WebGL自学网 WEB服务器 Nginx开发从入门到精通 (淘宝团队出品) Nginx教程从入门到精通(PDF版本,运维生存时间出品) OpenResty最佳实践 Apache 中文手册 版本控制 Git教程 (本文由 廖雪峰 创作,如果觉得本教程对您有帮助,可以去 iTunes 购买) git - 简易指南 猴子都能懂的GIT入门 Git 参考手册 Pro Git Pro Git 中文版 (整理在gitbook上) Git Magic GotGitHub Git权威指南 Git Community Book 中文版 Mercurial 使用教程 HgInit (中文版) 沉浸式学 Git Git-Cheat-Sheet (感谢 @flyhigher139 翻译了中文版) GitHub秘籍 GitHub帮助文档 git-flow 备忘清单 svn 手册 GitHub漫游指南 编辑器 exvim--vim 改良成IDE项目 笨方法学Vimscript 中译本 Vim中文文档 所需即所获:像 IDE 一样使用 vim Atom飞行手册中文版 Markdown·简单的世界 一年成为 Emacs 高手 Emacs 生存指南 Atom官方手册 NoSQL NoSQL数据库笔谈 Redis 设计与实现 Redis 命令参考 带有详细注释的 Redis 3.0 代码 带有详细注释的 Redis 2.6 代码 The Little MongoDB Book The Little Redis Book Neo4j 简体中文手册 v1.8 Neo4j .rb 中文資源 Disque 使用教程 Apache Spark 设计与实现 PostgreSQL PostgreSQL 8.2.3 中文文档 PostgreSQL 9.3.1 中文文档 PostgreSQL 9.5.3 中文文档 MySQL MySQL索引背后的数据结构及算法原理 21分钟MySQL入门教程 管理和监控 ELKstack 中文指南 Mastering Elasticsearch(中文版) ElasticSearch 权威指南 Elasticsearch 权威指南(中文版) Logstash 最佳实践 Puppet 2.7 Cookbook 中文版 项目相关 持续集成(第二版) (译言网) 让开发自动化系列专栏 追求代码质量 selenium 中文文档 Selenium Webdriver 简易教程 Joel谈软件 約耳談軟體(Joel on Software) Gradle 2 用户指南 Gradle 中文使用文档 编码规范 开源软件架构 GNU make 指南 GNU make 中文手册 The Twelve-Factor App 设计模式 图说设计模式 史上最全设计模式导学目录 design pattern 包教不包会 设计模式 Java 版 Web 关于浏览器和网络的 20 项须知 浏览器开发工具的秘密 Chrome 开发者工具中文手册 Chrome扩展开发文档 Grunt中文文档 gulp中文文档 Gulp 入门指南 移动Web前端知识库 正则表达式30分钟入门教程 前端开发体系建设日记 移动前端开发收藏夹 JSON风格指南 HTTP 接口设计指北 前端资源分享(一) 前端资源分享(二) 前端代码规范 及 最佳实践 前端开发者手册 前端工程师手册 w3school教程整理 Wireshark用户手册 一站式学习Wireshark HTTP 下午茶 HTTP/2.0 中文翻译 RFC 7540 - HTTP/2 中文翻译版 http2讲解 3 Web Designs in 3 Weeks 站点可靠性工程 大数据 大数据/数据挖掘/推荐系统/机器学习相关资源 面向程序员的数据挖掘指南 大型集群上的快速和通用数据处理架构 数据挖掘中经典的算法实现和详细的注释 Spark 编程指南简体中文版 编程艺术 程序员编程艺术 每个程序员都应该了解的内存知识(译)【第一部分】 取悦的工序:如何理解游戏 (豆瓣阅读,免费书籍) 其它 OpenWrt智能、自动、透明FQ路由器教程 SAN 管理入门系列 Sketch 中文手册 深入理解并行编程 程序员的自我修养 Growth: 全栈增长工程师指南 语言相关类 Android Android Design(中文版) Google Material Design 正體中文版 (译本一 译本二) Material Design 中文版 Google Android官方培训课程中文版 Android学习之路 Android开发技术前线(android-tech-frontier) Point-of-Android Android 一些重要知识点解析整理 Android6.0新特性详解 APP Apache Cordova 开发指南 AWK awk程序设计语言 awk中文指南 C/C++ C/C++ 中文参考手册 (欢迎大家参与在线翻译和校对) C 语言编程透视 C++ 并发编程指南 Linux C编程一站式学习 (宋劲杉, 北京亚嵌教育研究中心) CGDB中文手册 100个gdb小技巧 100个gcc小技巧 ZMQ 指南 How to Think Like a Computer Scientist (中英文版) 跟我一起写Makefile(PDF) GNU make中文手册 GNU make 指南 Google C++ 风格指南 C/C++ Primer (by @andycai) 简单易懂的C魔法 Cmake 实践 (PDF版) C++ FAQ LITE(中文版) C++ Primer 5th Answers C++ 并发编程(基于C++11) QT 教程 DevBean的《Qt学习之路2》(Qt5) C++ Template 进阶指南 libuv中文教程 Boost 库中文教程 笨办法学C C# MSDN C# 中文文档 .NET 类库参考 ASP.NET MVC 5 入门指南 超全面的 .NET GDI+ 图形图像编程教程 .NET控件开发基础 .NET开发要点精讲(初稿) Clojure Clojure入门教程 CSS/HTML 学习CSS布局 通用 CSS 笔记、建议与指导 CSS参考手册 Emmet 文档 前端代码规范 (腾讯 AlloyTeam 团队) HTML和CSS编码规范 Sass Guidelines 中文 CSS3 Tutorial 《CSS3 教程》 MDN HTML 中文文档 MDN CSS 中文文档 Dart Dart 语言导览 Elixir Elixir编程入门 Erlang 21天学通Erlang Fortran Fortran77和90/95编程入门 Go Go编程基础 Go入门指南 学习Go语言 Go Web 编程 (此书已经出版,希望开发者们去购买,支持作者的创作) Go实战开发 (当我收录此项目时,作者已经写完第三章,如果读完前面章节觉得有帮助,可以给作者捐赠,以鼓励作者的继续创作) Network programming with Go 中文翻译版本 Effective Go Go 语言标准库 Golang标准库文档 Revel 框架手册 Java程序员的Golang入门指南 Go命令教程 Go语言博客实践 Go 官方文档翻译 深入解析Go Go语言圣经(中文版) (GitBook) Groovy 实战 Groovy 系列 Haskell Real World Haskell 中文版 Haskell趣学指南 iOS iOS开发60分钟入门 iOS7人机界面指南 Google Objective-C Style Guide 中文版 iPhone 6 屏幕揭秘 Apple Watch开发初探 马上着手开发 iOS 应用程序 网易斯坦福大学公开课:iOS 7应用开发字幕文件 Java Apache Shiro 用户指南 Jersey 2.x 用户指南 Spring Framework 4.x参考文档 Spring Boot参考指南 (翻译中) MyBatis中文文档 MyBatis Generator 中文文档 用jersey构建REST服务 Activiti 5.x 用户指南 Google Java编程风格指南 Netty 4.x 用户指南 Netty 实战(精髓) REST 实战 Java 编码规范 Apache MINA 2 用户指南 H2 Database 教程 Java Servlet 3.1 规范 JSSE 参考指南 Java开源实现及最佳实践 Java 编程要点 Think Java Java 8 简明教程 JavaScript Google JavaScript 代码风格指南 Google JSON 风格指南 Airbnb JavaScript 规范 JavaScript 标准参考教程(alpha) Javascript编程指南 (源码) javascript 的 12 个怪癖 JavaScript 秘密花园 JavaScript核心概念及实践 (PDF) (此书已由人民邮电出版社出版发行,但作者依然免费提供PDF版本,希望开发者们去购买,支持作者) 《JavaScript 模式》 “JavaScript patterns”中译本 命名函数表达式探秘 (注:原文由为之漫笔翻译,原始地址无法打开,所以此处地址为我博客上的备份) 学用 JavaScript 设计模式 (开源中国) 深入理解JavaScript系列 ECMAScript 5.1 中文版 ECMAScript 6 入门 (作者:阮一峰) JavaScript Promise迷你书 You-Dont-Know-JS (深入JavaScript语言核心机制的系列图书) JavaScript 教程 廖雪峰 MDN JavaScript 中文文档 jQuery jQuery 解构 简单易懂的JQuery魔法 How to write jQuery plugin You Don't Need jQuery 如何实现一个类jQuery? Node.js Node入门 七天学会NodeJS Nodejs Wiki Book (繁体中文) express.js 中文文档 koa 中文文档 一起学koa 使用 Express + MongoDB 搭建多人博客 Express框架 Node.js 包教不包会 Learn You The Node.js For Much Win! (中文版) Node debug 三法三例 nodejs中文文档 orm2 中文文档 underscore.js Underscore.js中文文档 backbone.js backbone.js中文文档 backbone.js入门教程 (PDF) Backbone.js入门教程第二版 Developing Backbone.js Applications(中文版) AngularJS AngularJS最佳实践和风格指南 AngularJS中译本 AngularJS入门教程 构建自己的AngularJS 在Windows环境下用Yeoman构建AngularJS项目 Zepto.js Zepto.js 中文文档 Sea.js Hello Sea.js React.js React.js 中文文档 React webpack-cookbook React 入门教程 React Native 中文文档(含最新Android内容) Learn React & Webpack by building the Hacker News front page impress.js impress.js的中文教程 CoffeeScript CoffeeScript Cookbook The Little Book on CoffeeScript中文版 CoffeeScript 编码风格指南 TypeScipt TypeScript Handbook ExtJS Ext4.1.0 中文文档 Meteor Discover Meteor Meteor 中文文档 Angular-Meteor 中文教程 Chrome扩展及应用开发 LaTeX 一份其实很短的 LaTeX 入门文档 一份不太简短的 LATEX 2ε 介绍 (PDF版) LISP Common Lisp ANSI Common Lisp 中文翻譯版 On Lisp 中文翻译版本 Scheme Yet Another Scheme Tutorial Scheme入门教程 Scheme语言简明教程 Racket Racket book Lua Lua编程入门 Lua 5.1 参考手册 中文翻译 Lua 5.3 参考手册 中文翻译 Lua源码欣赏 OCaml Real World OCaml Perl Modern Perl 中文版 Perl 程序员应该知道的事 PHP PHP 官方手册 PHP调试技术手册(PDF) PHP之道:php-the-right-way (@wulijun版 PHPHub版) PHP 最佳实践 PHP 开发者实践 深入理解PHP内核 PHP扩展开发及内核应用 Laravel5.1 中文文档 Laravel 5.1 LTS 速查表 Symfony2 Cookbook 中文版(版本 2.7.0 LTS) Symfony2中文文档 (未译完) YiiBook几本Yii框架的在线教程 深入理解 Yii 2.0 Yii 框架中文文檔 简单易懂的PHP魔法 swoole文档及入门教程 Composer 中文网 Slim 中文文档 Lumen 中文文档 PHPUnit 中文文档 Prolog 笨办法学Prolog Python 廖雪峰 Python 2.7 中文教程 廖雪峰 Python 3 中文教程 简明Python教程 零基础学 Python 第一版 零基础学 Python 第二版 可爱的 Python Python 2.7 官方教程中文版 Python 3.3 官方教程中文版 Python Cookbook 中文版 Python3 Cookbook 中文版 深入 Python 深入 Python 3 PEP8 Python代码风格规范 Google Python 风格指南 中文版 Python入门教程 (PDF) 笨办法学 Python (PDF EPUB) Python自然语言处理中文版 (感谢陈涛同学的翻译,也谢谢@shwley 联系了作者) Python 绘图库 matplotlib 官方指南中文翻译 Scrapy 0.25 文档 ThinkPython ThinkPython 2ed Python快速教程 Python 正则表达式操作指南 python初级教程:入门详解 Twisted 与异步编程入门 TextGrocery 中文 API ( 基于svm算法的一个短文本分类 Python 库 ) Requests: HTTP for Humans Pillow 中文文档 PyMOTW 中文版 Python 官方文档中文版 Fabric 中文文档 Beautiful Soup 4.2.0 中文文档 用Python做科学计算 Sphinx 中文文档 精通 Python 设计模式 python 安全编程教程 程序设计思想与方法 知乎周刊·编程小白学Python Scipy 讲义 Python 学习笔记 基础篇 Python 学习笔记 模块篇 Python 标准库 中文版 Python进阶 Python 核心编程 第二版 CPyUG译 Python最佳实践指南 Python 精要教程 Python 量化交易教程 Django Django 1.5 文档中文版 正在翻译中 Diango 1.7 文档中文版 正在翻译中,目前只翻译了目录 Django 1.8.2 文档中文版 正在翻译中 Django 最佳实践 Django搭建简易博客教程 The Django Book 中文版 Django 设计模式与最佳实践 Django 网站开发 Cookbook Django Girls 學習指南 Flask Flask 文档中文版 Jinja2 文档中文版 Werkzeug 文档中文版 Flask之旅 Flask 扩展文档汇总 Flask 大型教程 SQLAlchemy 中文文档 web.py web.py 0.3 新手指南 Web.py Cookbook 简体中文版 Tornado Introduction to Tornado 中文翻译 Tornado源码解析 Tornado 4.3 文档中文版 R R语言忍者秘笈 Ruby Ruby 风格指南 Rails 风格指南 笨方法學 Ruby Ruby on Rails 指南 Ruby on Rails 實戰聖經 Ruby on Rails Tutorial 原书第 3 版 (本书网页版免费提供,电子版以 PDF、EPub 和 Mobi 格式提供购买,仅售 9.9 美元) Rails 实践 Rails 5 开发进阶(Beta) Rails 102 编写Ruby的C拓展 Ruby 源码解读 Ruby中的元编程 Rust rust book 中文翻译 rust primer Scala Scala课堂 (Twitter的Scala中文教程) Effective Scala(Twitter的Scala最佳实践的中文翻译) Scala指南 Shell Shell脚本编程30分钟入门 Bash脚本15分钟进阶教程 Linux工具快速教程 shell十三问 Shell编程范例 Swift The Swift Programming Language 中文版 Swift 语言指南 Stanford 公开课,Developing iOS 8 Apps with Swift 字幕翻译文件 C4iOS - COSMOS 读书笔记及其它 编译原理(紫龙书)中文第2版习题答案 把《编程珠玑》读薄 Effective C++读书笔记 Golang 学习笔记、Python 学习笔记、C 学习笔记 (PDF) Jsoup 学习笔记 学习笔记: Vim、Python、memcached 图灵开放书翻译计划--C++、Python、Java等 蒂姆·奥莱利随笔 (由译言网翻译,电子版免费) SICP 解题集 精彩博客集合 中文文案排版指北 Standard C 语言标准函数库速查 (Cheat Sheet) Git Cheatsheet Chs GitBook简明教程 JavaScript语言精粹 制造开源软件 提问的智慧 Markdown 入门参考 AsciiDoc简明指南 背包问题九讲 老齐的技术资料 前端技能汇总 借助开源项目,学习软件开发 前端工作面试问题 leetcode/lintcode题解/算法学习笔记 前端开发笔记本 测试相关 移动APP自动化测试优秀框架Appium API Reference V1.2.0 CN 在线教育 51CTO学院 Codecademy CodeSchool Coursera Learn X in Y minutes (数十种语言快速入门教程) shiyanlou TeamTreeHouse Udacity xuetangX 慕课网 (丰富的移动端开发、php开发、web前端、html5教程以及css3视频教程等课程资源) 极客学院 计蒜客 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6044143.html,如需转载请自行联系原作者
作者:玄魂工作室-钱海龙 问题 这篇手把手教你构建 C 语言编译器,里面有着这样的代码 void eval() { int op, *tmp; while (1) { if (op == IMM) {ax = *pc++;} // load immediate value to ax else if (op == LC) {ax = *(char *)ax;} // load character to ax, address in ax else if (op == LI) {ax = *(int *)ax;} // load integer to ax, address in ax else if (op == SC) {ax = *(char *)*sp++ = ax;} // save character to address, value in ax, address on stack else if (op == SI) {*(int *)*sp++ = ax;} // save integer to address, value in ax, address on stack } ... return 0; } 只看op == LC这段代码,ax是一个int类型,存放的值是char *指针类型地址,取完该地址所在的值再赋给变量ax 但是如此写代码,vim的youcomplete插件一直报错 那就举个例子 //test.c #include <stdio.h> int main() { int a = 1; int p = &a; printf("the result is %d\n",*((int*)p)); } 32位linux gcc v4.8.4 试试32位gcc ~$ gcc test.c -o test test.c: In function ‘main’: test.c:4:13: warning: initialization makes integer from pointer without a cast [enabled by default] int p = &a; ~$ ./test the result is 1 虽然有警告,依然能运行成功正确输出,接下来试试32位g++ ~$ g++ test.c -o test ltest.c: In function ‘int main()’: test.c:4:14: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive] int p = &a; 直接抛出错误 64位linux gcc version 5.4.0 试试64位gcc ch@ch-pc:~$ gcc test.c -o test test.c: In function ‘main’: test.c:4:13: warning: initialization makes integer from pointer without a cast [-Wint-conversion] int p = &a; ^ test.c:5:35: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] printf("the result is %d\n",*((int*)p)); ^ ch@ch-pc:~$ ./test 段错误 (核心已转储) 运行时才出错,那么试试64位g++ ch@ch-pc:~$ g++ test.c -o test test.c: In function ‘int main()’: test.c:4:14: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive] int p = &a; ^ test.c:5:41: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] printf("the result is %d\n",*((int*)p)); 编译不通过 当然-m32这种参数,就不讨论了 初步结论 g++编译的时候就认为是个错误,gcc32位编译可以正常运行,64位运行时报错 我们探讨一下原因,32位和64的int类型都是4个字节的,但是指针类型的大小不一致 #include <stdio.h> int main() { int *p; printf("the result is %lu\n", sizeof(p)); } 分别在32位和64位编译器(注意是编译器,64位系统也有可能有32位编译器)编译后,运行 32位结果为"the result is 4" 64位结果为"the result is 8" 本质原因 64位,gcc编译后,拿到test可执行程序,程序执行会出现段错误,现在来反汇编一下 //test.c #include <stdio.h> int main() { int a = 1; int p = &a; printf("the result is %d\n",*((int*)p)); } //编译 ~$ gcc test.c -o test // objdump反汇编命令 // -S 尽可能尽可能反汇编出源代码 // -M 因为个人习惯问题,不太会看AT&A的汇编,还是搞成intel的来看 // nl只是把上面的结果显示一下行数,-b 行的显示方式 // -ba //显示所有行号(包括空行) // -bt //显示所有行号(但不包括空行) ~$ objdump -S -M intel test | nl -ba 主要看一下,main函数 从138行开始看,对应着代码int a = 1,将数字1赋值给rbp栈上的-0x10处,也就是在距离bp栈的16字节处(因为0x10=16);如下图1行,B(地址)处的为数字1,占四个字节,那么中间竖线就是[rbp-0xc]处 139行,将地址传给了rax寄存器,注意rax是16字节(对应题目中的指针大小),对应下图2行,rax存储的就是(A,B) 140行,对应下图3行指令中eax是rax的低位,存储的值就是B(注意B是地址)四个字节,赋值给[rbp-0xc]处四个字节B(注意B是地址),而[rbp-0xc]到[rbp-0x10]还是数字1四个字节 最主要的问题出在141行,也就是把[rbp-0xc]的值,也就是B,赋值给rax的低位,本来这个rax的低位8个字节就是B,这个没问题,问题出在64位系统的给eax(rax的低位)赋值,会影响rax的高位,高位全被置为0了. 具体论证在这里 这样在143行,对应下图5行,尝试把rax寄存器的值当成地址,去该地址取值. rax寄存器的值是(0, B)(这里面是0, B各占8个字节,对应c代码里面的指针大小,16个字节),而实际需要的地址值是(A, B). 我们来用edb调试的结果,也跟想得一样 有一点我上面并没有讲到,就是上图4行的 rax 过渡到上图5行的时候高位并不一定是零,因为在142行的时候,有一个指令cdqe,这是eax拓展成rax的指令,所有要根据eax的正负性来判断.也就是说,如果eax表达出来是负数,rax的高位补出来的是全f;同理eax正数的情况下,rax高位补全的才是0 解决方案 在c99的标准库里面有一个结构体,intptr_t可以实现编译器位数兼容性 //头文件stdint.h /* Types for `void *' pointers. */ #if __WORDSIZE == 64 # ifndef __intptr_t_defined typedef long int intptr_t; # define __intptr_t_defined # endif typedef unsigned long int uintptr_t; #else # ifndef __intptr_t_defined typedef int intptr_t; # define __intptr_t_defined # endif typedef unsigned int uintptr_t; #endif 上述测试代码改成这样即可 #include <stdio.h> #include <stdint.h> int main() { int a = 1; int p = &a; printf("the result is %d\n",*((int*)(intptr_t)p)); } 原始代码改成下面即可 if(op == IMM) { ax = *pc++; } else if(op == LC) { ax = *(char *)(intptr_t)ax; } else if(op == LI) { ax = *(int *)(intptr_t)ax; } else if(op ==SC) { ax = *(char *)(intptr_t)*sp++ = ax; } else if(op == SI){ *(int *)(intptr_t)*sp++ = ax; } else if(op == PUSH) { *--sp = ax; } else if(op == JMP) { pc = (int *)(intptr_t)*pc; } else if(op == JZ) { pc = ax ? pc + 1 : (int *)(intptr_t)*pc; } else if(op == JNZ) { pc = ax ? (int *)(intptr_t)*pc : pc + 1; } else if(op == CALL) { *--sp = (int)(intptr_t)(pc + 1); pc = (int *)(intptr_t)*pc; } else if(op == ENT) { *--sp = (int)(intptr_t)bp; bp = sp; sp = sp - *pc++; } else if(op == ADJ) { sp = sp + (intptr_t)*pc++; } 参考 C---int和指针转换注意事项 Disabling “cast from pointer to smaller type uint32_t” error in Clang Why is “cast from ‘X*’ to ‘Y’ loses precision” a hard error and what is suitable fix for legacy code C语言指针转换为intptr_t类型 x86_64 registers rax/eax/ax/al overwriting full register contents [duplicate] CBW/CWDE/ 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6094660.html,如需转载请自行联系原作者
赠书:HTML5 Canvas 2d 编程必读的两本经典 这两年多一直在和HTML5 Canvas 打交道,也带领团队开发了世界首款基于HTML5 Canvas 的演示文档工具---AxeSlide(斧子演示,www.axeslide.com)。在这个领域也积累了一些 经验,希望有机会和大家分享。今天是要给大家推荐两本这方面的书,同时会送一本书给大家。 要介绍的第一本书是我学习Canvas开发的入门书——《HTML5 Canvas核心技术:图形、动画与游戏开发》。 此书作者David Geary,中文版译者为爱飞翔,由机械工业出版社出版。 我相信这本书,不仅是我个人,很多学习Html5 Canvas开发的同学都是把它当做案头必备。 这本书是HTML5 Canvas领域的标杆之作,也是迄今为止该领域内容最为全面和深入的著作之一,是公认的经典、五星级畅销书、资深技术专家David Geary力作。它不仅全面讲解了canvas元素的API,以及如何利用Canvas进行图形绘制、动画制作、物理效果模拟、碰撞检测、游戏开发、移动应用开发,还包含大量实例,可操作性极强。 我们在开发斧子演示的时候,从基本的绘图,图片,视频,音频处理,到动画、文本处理, 所有核心开发内容都能从这本书中获取知识和灵感。 《HTML5 Canvas核心技术:图形、动画与游戏开发》共分11章。第1章介绍了canvas元素及如何在网络应用程序中使用它;第2章深入研究了如何使用Canvas的API进行绘制;第3章告诉读者如何绘制并操作Canvas中的文本;第4章专门讲解图像、图像的操作及视频处理;第5章介绍如何实现平滑的动画效果;第6章讲解如何用JavaScript语言来实现精灵;第7章展示了如何在动画中模拟物理效果;第8章介绍了进行碰撞检测所用的技术;第9章以一个简单但是高效的游戏引擎开始,提供了游戏制作所需的全部支持功能;第10章讨论了实现自定义控件的通用方法;第11章专门讲述如何实现基于Canvas的手机应用程序。 上面的书已经成为经典,接下来的这本,即将成为经典。同样是大牛David Geary的力作——《HTML5 2D游戏编程核心技术》。 此书由机械工业出版社出版,目前你在网上和实体书店还买不到这本书,不过我已经提前拿到了,并且仔细 阅读了几天。 相对于上一本书,此书可作为Html5 Canvas编程的进阶书来读,同时可以作为HTML5游戏编程 的入门宝典来长期翻阅。 大师与普通人的区别,不仅仅在于能力的高低,更重要的是能把知识讲明白,真正做到传道、 授业、解惑。 这本书做到了。 本书是为希望使用HTML5进行2D游戏开发,且具备一定JavaScript编程经验的开发人员而准备的。在本书中,笔者从零开始完整讲解了一个复杂的横向卷轴平台视频游戏的开发过程,并将该视频游戏命名为“Snail Bait”。在开发过程中,笔者没有使用任何第三方图形框架或游戏框架,因此读者将从本书中学会以编程方式实现平滑动画、sprite爆炸、开发人员后门程序、游戏难易度设计等所有内容。如果读者正在使用某个游戏框架开发游戏,那么本书对于帮助读者理解游戏框架内部的工作原理也同样大有裨益。 出于教学目的,Snail Bait游戏仅实现了一个关卡,然而它却具备了街机风格游戏的全部特点。Snail Bait游戏在滚动的背景上同时操作多个动画对象,即sprite对象,在播放游戏背景音乐的同时添加多种音频效果。sprite对象具备多种行为,包括但不限于跑动、跳跃、飞行、闪光、弹跳、来回移动、爆炸、碰撞、平台着陆、从游戏画面底部跌落等。 另外,Snail Bait游戏还实现了多个特色功能。例如,一个可以减慢或加快游戏整体速度的时间系统;游戏加载过程动画;当游戏主角失去生命时,震动游戏画面的特殊效果;模拟烟雾和燃烧的粒子系统等。当游戏窗口失去焦点时,Snail Bait游戏会暂停运行,而当游戏窗口重新获得焦点时,Snail Bait游戏会以一个倒计时动画作为开始,以便玩家有时间来恢复对游戏的控制。 虽然没有使用游戏框架或图形框架,但是Snail Bait游戏使用Node.js和socket.io技术实现了将游戏中的一些指标数据发送到服务器端、高分存储和检索,并在游戏窗口顶部显示高分榜等功能。当游戏运行缓慢时,Snail Bait游戏还将显示警告信息。而当按下“Ctrl+D”组合键启动游戏时,Snail Bait游戏将启动开发人员后门程序,从而赋予操作人员特殊权限,例如修改时间轴的流动,或者显示sprite对象碰撞检测矩形以及其他功能等。 当Snail Bait游戏检测到自己运行在移动设备上时,将通过调用触摸事件处理句柄、调整游戏窗口大小来重新配置自身,以便适应移动设备的屏幕大小及控制方式。 游戏编程一直以来是我练习编程技能的最佳训练方法。因为哪怕一个小小的游戏,你也要考虑 程序的架构,考虑分层和解耦,考虑消息传递,考虑绘图,考虑动画,考虑网络,考虑性能, 考虑交互,多媒体处理,多线程等等。游戏编程,往往需要我们在某一方面做到极致,对编程者 的磨练是相当大的。从一个小游戏的编写中,我们能系统学习很多知识和技巧。 以上是我极力推荐此书的原因,此书不难,只要你用心,都能看懂,而且作者还配备了视频教程。 更主要的原因是作者写的足够好! 两本经典,各一本送给大家,每人只能得其中一本。参与方式如下: 0. 微信扫描关注 玄魂工作室 (xuanhun521) 1.如果你可以写出HTML5 Canvas 相关的优秀文章,请在微信订阅号本文下面留言投稿给我。如果你的稿件被采纳,我会立即送书一本。 2.随机打赏,并在此文章下留言。我会随机抽取幸运者。 机械工业出版社华章图书在赠书给玄魂工作室的读者之外,还给了我全网最低价的购书优惠, 大家通过我可以以 75折+5元邮费的方式买到这两本书。如果你想购买,直接文章下留言就好。 这是我个人独享的优惠,没有任何中间利润,如果你有更便宜的方式买,也请推荐给我,但不要说三道四,无中生有。 两本书的定价均为 人民币99元。 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6123303.html,如需转载请自行联系原作者
错误信息: 加载该页时出错。 未找到与约束 ContractName Microsoft.CodeAnalysis.Editor.TypeScript.ScriptContexts.ITypeScriptPr 解决方法: 1.关闭VS; 2.去C:/Users/<your users name>/AppData/Local/Microsoft/VisualStudio/12.0/ComponentModelCache文件夹下删除所有文件及文件夹; 3.重新打开VS即可。 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6180461.html,如需转载请自行联系原作者
在上一节,我们完成了编写一个简易的Sniffer的第一步——数据捕获。 很多时候,我们需要将捕获的数据先保存到磁盘上,之后再使用工具或者自己编写代码来进行详细分析。 本节我们在上一节的基础上来讲解保存捕获数据的方式,当然使用tcpdump或者WireShark都可以 很方便的存储数据包。 4.2.1 使用pcapy保存和读取数据 前文我们使用 pcapy的open_live方法,可以获取pcapy的一个实例对象,通过该对象的dump_open 方法可以获取一个dump对象,通过dump对象可以保存数据包到本地磁盘。示例如下: #!/usr/bin/python import pcapy dev = "eth0" filter = "tcp and port 80" def save_packet(hdr, data): dumper.dump(hdr, data) pcap = pcapy.open_live(dev, 1500, 0, 100) dumper = pcap.dump_open('sniffer.pcap') pcap.setfilter(filter) pcap.loop(0, save_packet) 上面的代码中,我们首先通过dump_open方法获取dumper对象,随后在循环捕获数据的时候 调用save_packet方法,该方法中调用dump方法将数据保存到本地。运行结果如下: 下面我们看看如何从磁盘读取pcap文件。 #!/usr/bin/python import pcapy dev = "eth0" filter = "tcp and port 80" def read_packet(hdr, data): print data pcap = pcapy.open_offline('sniffer.pcap') pcap.loop(0, read_packet) 在上面的带码中,我们使用pcapy的open_offline方法从本地打开一个pcap文件,之后就可以 循环处理每一个数据包了。运行结果如下: 4.2.2 使用Scapy保存和读取数据 上一节我们讲了Scapy的基础用法,Scapy支持将捕获的数据保存成多种数据格式,比如hex,base64等, 利用Scapy来保存捕获的数据到pcap文件,有两种方式,第一种为使用PcapWriter模块,例如: from scapy.all import * from scapy.utils import PcapWriter def packetHandler(pkt): pktdump.write(pkt) pktdump = PcapWriter("ssss.pcap", append=True, sync=True) sniff(filter='tcp and port 80',prn=packetHandler,iface='eth0') 初始化PcapWriter对象需要传入三个参数,要保存的文件名、是否追加数据,是否同步顺序添加。 之后在packetHandler方法中,调用write方法将数据包写入文件。运行结果如下: 另外一种方式为配置sniff方法的offline参数。例如: sniff(filter='tcp and port 80',iface='eth0',offline="temp.cap") 读取pcap文件可以使用scapy.all 模块中的rdpcap方法。例如: from scapy.all import * packets = rdpcap('ssss.pcap') for packet in packets: print packet 如上,rdpcap方法接收一个文件路径参数,返回所有的数据包。运行结果如下: 4.2.3 小结 读取和保存数据的方法很多,这里结合本教程实例,只介绍这两种较为简单的方法。 查看更多Python黑客编程及安全类文章,请关注玄魂工作室微信订阅号(xuanhun521)。 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6383083.html,如需转载请自行联系原作者
Python爬虫之urllib模块1 本文来自网友投稿。作者PG,一个待毕业待就业二流大学生。玄魂工作室未对该文章内容做任何改变。 因为本人一直对推理悬疑比较感兴趣,所以这次爬取的网站也是平时看一些悬疑故事的网站,同时也是因为这个网站在编码上面和一些大网站的博客不同,并不那么规范,所以对于初学者还是有一定的挑战性的。我打算把这个爬虫分三次讲,所以每次都先完成一个小目标(当然不是一个亿啦),这次课我们先爬取当前页面的并且下载第一篇文章。第二次课我们就将爬取当前页面的=所有的链接进行下载,第三次课我们将把整个板块的文章都下载下来。 演示系统用的是kali,因为懒得去配置各种py模块了,就利用系统已经配置好的,浏览器是firefox,使用的IDE是微软的vscode 首先我们选取了我们要爬取的网站http://tuilixue.com/,先检查一下robots.txt看看是否存在有一些反爬虫的信息 很好,这里没有什么限制 然后我们到我平时比较常去的板块看看,http://tuilixue.com/zhentantuilizhishi/list_4_1.html我们现在想要爬取的文章就是这样的 右击鼠标查看源代码,我们可以看到,我们想要爬取的链接就是这样的 来一张清晰的 但是我们要怎么办才能使python得到这个网页的源代码呢 我们可以使用python的urllib模块提供的open方法,首先我们先新建一个py文件,惯例 #-*-coding:utf8-*- #!usr/bin/python 因为是linux系统,所以python路径不同于windows,第一行代码说明是用的uft-8进行编码 在这里我们要先导入urllib这个模块,使用import导入 这里其实是两个方法,一个open一个read,open用于从网站上获取网页代码,read是为了读出来好打印 我们可以得到上面结果,但是我们发现字符似乎成了乱码,为了找到原因,我们再来看看源码 我们似乎找到了原因,网页使用的是gb2312进行编码的,但是我们是使用utf-8的,所以导致的乱码,对这方面不解的同学可以去找一些编码的知识看看。下面我们用一个编码转换来尝试获取正确的编码 大家这时可以看到,我们通过强制的编码将获取的网页重新通过gb2312进行编码,我们就可以看到正确的字符了,但是在我们的这次课中并不需要这样的转码,这里只是为了显示获取的是正确的网页,从图中看到,我们获取的正是我们需要进行爬取的页面。 下一步,我们需要获取我们本页的所有的文章链接了,这里需要有一点html和css的知识,关于这部分的知识,大家自己去掌握就行了,不需要太深入。如图中显示的,href后面的就是我们在本次课中需要爬取的链接,每页都有10篇文章是我们需要爬取的,我们先从第一篇的链接开始。 这时候我们就要想我们应该怎么样去获取到这个页面的链接了,如果正则表达式好的同学应该是想到了采取正则表达式进行获取,但是这里有一个问题,一个html页面中有如此多的a开头的元素,也有如此多的href开头的元素,想要通过正则去定位还是有点难的,就算定位出来,也是一大堆的代码,这就不利于可读性了。这时我们应该再从html文本中去分析。我们使用type函数进行类型的判断。 通过对pageContent的类型分析,我们知道这是一个字符串类型 这样我们就可以使用字符串中的find函数了,我们需要对find函数有一个了解 函数中说明了从字符串中寻找目标字符,返回找到的第一个下标,如果没有找到就返回-1,同时可以设置开始寻找的位置和结束的位置。 我们再看到文本 我们发现是在div class=“liszw”下的li元素中的a元素中含有我们需要的链接,这时我们一个个来分析。 Li不能作为我们的选择了 a也不行 这个数量就比较接近了,我再看看前后文的规律发现/span><a似乎是符合我们的要求的 这时我们发现这和我们所要爬取的链接数量上是完全吻合的。我们就来试试。 这里我们采取了一个切片操作,这时我们发现链接其实已经爬取到了,但是还是有些不完美,我们再来完善一下他。 我们来对比一下我们的网页上的第一个链接 这样我们就成功的爬取了第一个链接,现在我们来准备下载第一篇文章。从前面我们可以知道,我们可以把网页通过python的urllib模块下载下来,那么同样的道理,我一样也可以通过urllib模块对文章进行下载。我们通过链接的最后一串数字对下载下来的文件进行命名。并在下载玩后打印end进行提示。 我们可以看到,路径下是没有文件的。现在我们开始下载。 从这里看我们的文件应该是下载成功了,我们去文件路径下面看看。 文件下载是成功了,我们来打开看看。这个地方要注意地址栏的链接 这样,我们第一篇的文章就下载成功了。 未完,待续。请持续关注 微信订阅号:玄魂工作室(xuanhun521) 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6708377.html,如需转载请自行联系原作者
Python爬虫之urllib模块2 本文来自网友投稿 作者:PG-55,一个待毕业待就业的二流大学生。 看了一下上一节的反馈,有些同学认为这个没什么意义,也有的同学觉得太简单,关于BeautifulSoup和lxml在后续的教程都会有。这里我记录的是我学习和思考的一个过程,我不是编程高手,非常感谢玄魂老师能给我这个机会,在公众号发布这种入门文章。 上一课我们成功的下载了页面的第一篇文章,这一课我们的目标是怎么把第一页的所有文章都下载下来。还是先继续我们上一节课的内容。我们这次爬取的网页还是http://tuilixue.com/zhentantuilizhishi/list_4_1.html 上一次课我们说了怎么去获取第一条的文章链接,现在我们再来爬取本页后面剩下的链接。我们先来看看上次我们爬取链接用的代码。 获取后面的链接我们能不能如法炮制呢,我们先来试试。我们把代码写成下面那样 然后我们现在来试试 结果我们发现我们试图获取的三条链接都是一样的,可以看出,这还是本页的第一篇文章的链接。证明我们这种方法是不可行的。我们回想一下上一节课我们讲的定位链接使用函数 就是这个find函数,我们看看帮助,我们发现了我们可以自定义开始寻找的下标和寻找结束的下标。我们从html里面发现我们想要爬取的链接相隔都不是很远,都处在同一个div下面。于是我们来试试,从第一条链接后面开始寻找第二条链接。 这里我们要注意后面两条代码,我们选择了开始的下标是从上一条链接的尾部开始的。现在我们来试试是否可以获取正确的链接。 现在我们获取到了三条不同的链接,我们再通过对比html来看看我是否获取的是正确的链接。 从结果来看,我们的代码成功的获取了本页的前几篇文章的链接。关于怎么获取剩下的链接我们应该有头绪了。当然,这里一页只有10篇文章,也就是只有10个链接,我们可以把我们的获取链接的代码复制10次,可是如果一页有20篇,30篇,50甚至是100篇呢,难道我们也要将代码复制那么多的次数,肯定不能,也不科学。很多同学现在已经知道要用循环来做了,但是这个要怎么循环,从哪里循环呢?我们再来看看我们上面的代码,我们发现除了第一条链接获取的代码不一样,后面两条链接获取的代码都是一样的,这时我们就知道我们应该从第二条链接获取代码进行循环了。 这里我们要先定义一个列表对获取的链接进行存储,因为是10篇文章,所以这里定义的就是一个10个元素的空的字符串列表。下面是我们循环的代码块。 这里结束一下我们为什么不是从0开始进行赋值,大家注意到没有,我们是从第二条文章链接看是循环的,那么第一条的文章链接在哪呢?当然是存储在了列表的第一个位置,也就是下标为0的那个位置了,关于range后面的范围,大家知道是包下不包上的就行了,就是说在range(x,y)的循环中,循环是从x开始,到y-1结束的,不包括y本身。我们现在来运行一下我们的代码看看是否获取的是正确的链接。 然后再次对比html 这时我们发现我们获取了链接是正确的,那么我们就要开始进行下载了。还是上一节课的代码,不过我们进行修改一些地方。因为上次只是单个链接,这次我们有一个链接列表,所以我们应该采取循环进行下载。我们要对下载重新写一个循环了。 我们现在来试试,这是上一节课我们成功下载的第一篇文章 我们现在删掉他。 现在我们看到文件夹里面是什么都没有的,我们现在开始下载。 我们这就下载完了,我打开其中一个看看。还是注意地址栏上面的链接。 可以看出我们获取的文章是正确的。因为篇幅有限,我就不一个一个去打开截图了,大家自己可以根据自己实际环境敲一下代码。 类似的功能有很多值得改进的点,大家可以发表自己的观点,进行讨论。 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6719274.html,如需转载请自行联系原作者
原创 2017-05-31 玄魂工作室 玄魂工作室 打起精神,重新开启订阅号的原创文章写作工作,但是需要点时间,请耐心等待。 求资料的同学,没有及时回复的,请再次留言,我会尽快处理。今天分享两本电子书,虽然是英文的,但是难度不高。 第一本是基于Kali 2.0 的web渗透测试 链接: http://pan.baidu.com/s/1slLgAAD 密码: 8gvn 第二本是基于Hadoop的大数据取证技术 链接: http://pan.baidu.com/s/1qY37DMG 密码: 2cax 欢迎关注玄魂工作室 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6928166.html,如需转载请自行联系原作者
原创 2017-06-01 玄魂工作室 玄魂工作室 今天是六一儿童节,首先祝所有的小朋友身体健康,能永远生活在一个没有战争,没有压迫的世界里,永远快乐。 上一篇文章,很多人都对Python的各种书籍感兴趣,我也会尽我所能,给大家做些推荐。本次推荐的是Python的入门书籍,尽量的推荐浅显易懂的书。 很多书虽然比较老,但是并不是没有价值,希望大家不要执着于是2.0 还是3.0 的问题,学习本质,让你更好的面对变化。 我给到的电子书基本都是英文的,来自公开途径。如果你喜欢中文书籍,可以去购买或者自行寻找。如果手机上打开链接找不到资源,请在PC上打开。 当然,我们不是专门学Python的人群,其他语言和技术的入门书籍,也会不定期进行推荐,也欢迎大家参与讨论。 《与孩子一起学编程》 内容简介 · · · · · · 一本老少咸宜的编程入门奇书!一册在手,你完全可以带着自己的孩子,跟随Sande父子组合在轻松的氛围中熟悉那些编程概念,如内存、循环、输入和输出、数据结构和图形用户界面等。这些知识一点儿也不高深,听起来备感亲切,书中言语幽默风趣而不失真义,让学习过程充满乐趣。细心的作者还配上了孩子们都喜欢的可爱漫画和经过运行测试的程序示例,教你用最易编写和最易理解的Python语言,写出你梦想中的游戏程序。 “Hello, World!我来了!”编程乐趣无穷,起点就在脚下,请引导你的孩子走进这奇妙的世界。无论是中小学生还是其他初学者,都可以跟随本书学习Python编程,并过渡到任何其他语言,重要的是你将学会思考问题和解决问题的方法。 作者简介 · · · · · · Warren Sande 毕业于加拿大里贾那大学电气工程系。一直在面向计算机初学者教授软件基础课程,编写过大量广受欢迎的技术文档。 Carter Sande Warren之子,一个聪明、热情、好奇心强、喜欢思考问题的小男孩,热爱计算机,喜欢弹钢琴和玩超级玛丽。很小的时候就开始跟着父亲玩编程。 这本书不仅适合编程入门,还适合你学英语,因为作者的用词都很简单,易懂。 英文电子书下载链接 链接: http://pan.baidu.com/s/1jHCXkb0 密码: u2ir 《笨办法学Python》 这本书以习题的方式引导读者一步一步学习编程,从简单的打印一直讲到完整项目的实现,让初学者从基础的编程技术入手,最终体验到软件开发的基本过程。 本书结构非常简单,共包括52个习题,其中26个覆盖了输入/输出、变量和函数三个主题,另外26个覆盖了一些比较高级的话题,如条件判断、循环、类和对象、代码测试及项目的实现等。每一章的格式基本相同,以代码习题开始,按照说明编写代码,运行并检查结果,然后再做附加练习。 Zed Shaw完善了这个堪称世上最好的Python学习系统。只要跟着学习,你就会和迄今为止数十万Zed教过的初学者一样获得成功。 在这本书中,你将通过完成52个精心设计的习题来学会Python。阅读这些习题,把习题的代码精确地写出来(禁止复制和粘贴!),修正你的错误,观察程序的运行。在这个过程中,你将了解软件是如何工作的,好的程序看起来是什么样子,怎样阅读、编写、思考代码,以及如何用专业程序员的技巧来找出并修正错误。最重要的是,你将学到下面这些编写优秀的Python软件必需的初始技能。 英文电子书下载链接 链接: http://pan.baidu.com/s/1dFvgG6X 密码: cvri 《A Byte of Python》 对想要简洁完整地学习Python的人来说,本书是一本非常有价值的阅读材料。《A Byte of Python》采用清晰的结构框架,引导读者了解主题的核心元素。另外,书本流畅的写作风格和大量的插图、图表,让读者能够更加透彻地了解复杂的概念。 在线阅读地址 https://python.swaroopch.com/ 更多电子书,学习资料,视频教程,请扫码关注订阅号 回复“zy”。 kali linux 2.0 web 渗透测试 电子书 HTML5 Canvas 2d 编程必读的两本经典 这些安全类书籍,值得一读 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6932783.html,如需转载请自行联系原作者
原创 2017-06-03 玄魂工作室 玄魂工作室 继续上一次的Python编程入门的资源推荐,本次为大家推荐的是Python网络安全相关的资源和书籍。 在去年的双11送书的时候,其实送过几本Python黑客编程的书,说实话,国内编写或者翻译的这类书籍并没有太好的,说不好,主要原因是都停留在网络编程的简单应用上,入门尚可。 下面简单罗列几本,仅供参考。 《Python 黑帽子:黑客与渗透测试编程之道》 本书由 Immunity 公司的高级安全研究员 Justin Seitz 精心撰写。作者根据自己在安全界,特别是渗透测试领域的几十年经验,向读者介绍了 Python 如何被用在黑客和渗透测试的各个领域,从基本的网络扫描到数据包捕获,从 Web 爬虫到编写 Burp 扩展工具,从编写木马到权限提升等。 作者在本书中的很多实例都非常具有创新和启发意义, 如 HTTP 数据中的图片检测、 基于 GitHub命令进行控制的模块化木马、浏览器的中间人攻击技术、利用 COM 组件自动化技术窃取数据、通过进程监视和代码插入实现权限提升、通过向虚拟机内存快照中插入 shellcode 实现木马驻留和权限提升等。通过对这些技术的学习,读者不仅能掌握各种 Python 库的应用和编程技术,还能拓宽视野,培养和锻炼自己的黑客思维。读者在阅读本书时也完全感觉不到其他一些技术书籍常见的枯燥和乏味。 《Python绝技:运用Python成为顶级黑客》 这本书翻译过来的名字很牛逼,但是很遗憾,并不能让你达到多高的水平,这本书介绍了很多小技巧。仅此而已。 《Python灰帽子:黑客与逆向工程师的Python编程之道》 这是我要隆重推荐的第一本书,可能你已经买不到这本书了,但是很容易在网络上找到它的电子版。我是在上大学的时候第一次读的此书的英文版,受益匪浅。 虽然很多内容有点过时,但是方向和思想,基本的编程方法都值得学习。 《Python灰帽子:黑客与逆向工程师的Python编程之道》是由知名安全机构Immunity Inc的资深黑帽Justin Seitz先生主笔撰写的一本关于编程语言Python如何被广泛应用于黑客与逆向工程领域的书籍。老牌黑客,同时也是Immunity Inc的创始人兼首席技术执行官(CTO)Dave Aitel为本书担任了技术编辑一职。本书的绝大部分篇幅着眼于黑客技术领域中的两大经久不衰的话题:逆向工程与漏洞挖掘,并向读者呈现了几乎每个逆向工程师或安全研究人员在日常工作中所面临的各种场景,其中包括:如何设计与构建自己的调试工具,如何自动化实现烦琐的逆向分析任务,如何设计与构建自己的fuzzing工具,如何利用fuzzing测试来找出存在于软件产品中的安全漏洞,一些小技巧诸如钩子与注入技术的应用,以及对一些主流Python安全工具如PyDbg、Immunity Debugger、Sulley、IDAPython、PyEmu等的深入介绍。作者借助于如今黑客社区中备受青睐的编程语言Python引领读者构建出精悍的脚本程序来一一应对上述这些问题。出现在本书中的相当一部分Python代码实例借鉴或直接来源于一些优秀的开源安全项目,诸如Pedram Amini的Paimei,由此读者可以领略到安全研究者们是如何将黑客艺术与工程技术优雅融合来解决那些棘手问题的。 英文电子书下载 链接: http://pan.baidu.com/s/1pLjWX8R 密码: 2qjy 中文电子书下载 链接: http://pan.baidu.com/s/1pLe70Jx 密码: 3ixk 《Understanding.Network.Hacks.Attack.and.Defense.with.Python》 此书值得推荐,是因为它聚焦于网络七层模型的编程和安全问题。书中的示例虽然简单,但是我们完全可以在此基础上扩展出很丰富的内容。 从理解网络协议本身去理解网络安全,理解网络安全编程。 我目前创作的《Python 黑帽编程》系列教程,也是以此书为主要参考资料来扩展的。 英文电子书下载 链接: http://pan.baidu.com/s/1dEPsIGx 密码: 9kqh 快到12点了,我们先推送到这,明天微信订阅号再继续。 更多电子书,学习资料,视频教程,请订阅号 回复“zy”。 儿童节,我们从零开始——Python入门资源推荐 kali linux 2.0 web 渗透测试 电子书 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6938073.html,如需转载请自行联系原作者
虽然要讲解的知识点是通用的,但是还是要介绍下我的应用场景和测试环境。 0.1 应用场景和测试环境 我的应用是一块使用Html Canvas开发的黑板,在黑板上实现简单的文字编辑功能。 操作系统:win10 设备:为触屏和非触屏设备若干(一体机,surface,笔记本电脑) 主要浏览器: chrome 58 1.png 0.2 监控文字输入的方法 使用Canvas实现文字编辑器的细节这里就不讲了,原理大致都相同。一个必要条件是需要一个隐藏的textarea监听文字输入,因为canvas是无法记录文字选中、换行等信息的,也没有办法直接激活输入法和软键盘。textarea 如下: <textarea id="ghostTextArea" tabindex="0" style="width: 1000px; height: 1px; position: static; top: 0px; z-index: 5; opacity: 0; display: block;"></textarea> 很多情况下,我们需要实时监控文字输入的变化,下面是几种选择。 0.2.1 键盘事件 监听keydown 和 keyup事件是最直接的方法,通过keyCode我们可以获取按键值。 this.hiddenTextArea.onkeyup = (e) => { console.log("textKeyup",e.keyCode); } this.hiddenTextArea.onkeydown = (e) => { console.log("textKeydown",e.keyCode); } 0.2.2 oninput事件 input事件在keydown事件触发之后被触发,这是input类型元素使用的标准事件,表示有文字输入。 2.png 从上图中我们可以看到,触发的事件为InputEvent,从该事件对象的data属性中可以获取到当前输入的按键值。 正常情况下,每一次按键都会触发oninput事件。 0.2.3 onpropertychange 事件 该事件主要是为了兼容IE9及以下浏览器对oninput事件的处理。 在监听到 onpropertychange 事件后,可以使用 event 的 propertyName 属性来获取发生变化的属性名称。 // Internet Explorer function OnPropChanged (event) { if (event.propertyName.toLowerCase () == "value") { alert ("The new content: " + event.srcElement.value); } } 0.3 非直接输入模式 我们把及时响应键盘按键输入单个按键代表的字符到文本框的行为称为直接输入模式,相对的非直接输入模式,通常是输入法拦截了按键消息之后的输入,以中文输入法为例,通常是回车或者空格后完成输入。 3.png 在非直接输入模式下,我们期待的结果是当用户完成输入的时候(按了空格或者回车键)触发一次oninput事件。但是很不幸,每次按键都会触发oninput事件,这会导致我们不知道用户正在输入的是不是中文,也不知道什么时候结束的输入,也就没办法及时对输入的中文进行处理。 为了解决这个问题,我们看一下非直接输入情况下几个有用的属性和事件。 0.3.1 selectionStart 和 selectionEnd 这两个属性是textarea对文字选中区域的标识,从0开始,简化分析,我们只考虑正常文字输入,不考虑有选中的情况,首先是直接输入模式。 4.png 上图是我在oninput事件中打的日志,可以明显的看到每次oninput触发之后,selectionStart和selectionEnd的值都相同而且表示最后一个文本,视觉上是我们看到的光标所在的位置,如果我们挪动光标,这两个值也会变化。这里我们提取两个关键特征,在及时输入的情况下: selectionStart和selectionEnd随光标位置变化而变化 selectionStart和selectionEnd值相等 下面我们再看非直接输入模式。 5.png 从上图中,我们可以看到在非直接输入模式下,在未完成输入之前,selectionStart一直为0,selectonEnd随着输入一直变化。完成输入时,selectionStart与selectonEnd值会相等。 0.3.2 value 从0.3.1的图中我们可以看到拼音输入法输入过程中,value值的变化,在完成输入之前这个值是由输入法控制的,完成之后,value的值会变为输入的文字内容。 0.3.3 compositionstart 与 compositionend 事件 这是一对事件,当非直接输入开始第一个按键的时候,触发compositionstart事件,非直接输入结束的时候触发compositionend事件, 在直接输入情况下,这两个事件都不会触发。我们添加对这两个事件的监听: this.hiddenTextArea.addEventListener('compositionstart', function () { console.log("compositionstart"); that.isCompositionsting = false; }) this.hiddenTextArea.addEventListener('compositionend', function () { console.log("compositionend"); that.isCompositionsting = false; }) 6.png 观察上图的输出内容,各个事件的执行顺序为: keydown-->compositionstart-->input-->keyup....-->input-->compositionend-->keyup。 0.3.4 keyCode 现在我们观察下在非直接模式下,按键的值。 this.hiddenTextArea.onkeyup = (e) => { console.log("keydowncode",e.keyCode); } this.hiddenTextArea.onkeydown = (e) => { console.log("keyupcode",e.keyCode); } 7.png 通过上图,我们可以看到不论你按下的是什么键,keycode都被重置为229了。当然这并不是什么标准,不同输入法的行为还是不一样的。不过目前我们能接触到的中文输入法,正常情况下都是229。 0.4 思路整理 通过上面的分析,我们重新整理下及时响应非直接输入的思路。 0.4.1 如何知道正非直接输入的开始和结束 响应compositionstart事件和compositionend事件 比较selectionStart 和 selectionEnd是否相等。通常需要一个变量来标识开始和结束,考虑有选中的情况,这两个值可能会经历“相等--不等--相等”(或者 “不等--不等(相差为1)--不等(值增加)--相等”)的流程。 *判断按键的code是否为229,当然这也需要额外的变量来记录开始,还需要结合electionStart 和 selectionEnd才能判断出结束。 下面以selectionStart 和 selectionEnd为例,判断中文输入的开始和结束(非完整代码)。 this.hiddenTextArea.oninput = (e) => { if (textArea.selectionStart == textArea.selectionEnd) { editor.bdCanvas.textEditor.currentText.text = textArea.value; if (!isCompositionsting && 没有文字选中情况) { //直接插入ascii字符 } else { //插入文字(如果有部分文字被选中并替换) //先删除被选中的文字 if (isCompositionsting) {//中文(中文输入法按空格之后,或者回车后输入的字符) isCompositionsting = false; } else {//英文、数字 (有选中内容被替换) } } } else {//到这儿说明输入的是中文(中文输入法未按空格之前) isCompositionsting = true; } } 上面的代码引入了isCompositionsting变量,结合selectionStart和selectionEnd来做文字处理。其他方法同理,这里就不过多讲解了。下面我们来分析点异常情况。 0.5 搜狗输入法的非常规套路 8.png 这是我安装的最新的搜狗输入法,下面要说的非正常情况,只在这一个版本下会出现。 我们在代码中对keydown,keyup,input,compositionstart和compositionend同时做事件监听,然后使用这个版本的搜狗输入法做输入。结果如下: 9.png 在未按下回车或者空格键之前,我们看到: textarea只响应了keydown和keyup事件 keyup时keyCode并不是229 过程中没有触发input事件 再看结束输入时的情况: 10.png 上图红框内的内容为结束输入时的记录,此时触发一次input事件,selectionStart和selectionEnd相等。 这种情况,结束输入触发一次input,我倒是认为很合理的做法,这样很多情况我们不用关心是否是中文输入了,input的时候获取新的value,记录上一次的selectionstart就可以了。 这种特殊行为我没有具体研究是输入法本身的问题,还是和浏览器、操作系统共同作用的结果。如果你编写类似的程序,需要额外注意下。 0.6 小结 本篇文章只是分析记录了一些现象,并没有什么技术含量,欢迎留言讨论。 玄魂工作室 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/7053782.html,如需转载请自行联系原作者
原创 2017-06-05 玄魂工作室 玄魂工作室 我翻了翻我自己曾经看过的书,还是放弃了推荐。原因很简单,我对这个领域并不是很熟悉,我来推荐资源有点误人子弟。so,简单推点其他人建议给我的内容,希望对大家有用。 --------------------------------------------------------------------------- 首先 是github上是一个资源列表,资源的优劣我没有办法准确的评说,大家自己看吧。 https://github.com/rasbt/python-machine-learning-book 其次是一本书,《Packt.Artificial.Intelligence.with.Python》。 ’ 电子书下载地址:链接: http://pan.baidu.com/s/1kUJGYEz 密码: yhyt 更多电子书,学习资料,视频教程,请订阅号 回复“zy”。 儿童节,我们从零开始——Python入门资源推荐 kali linux 2.0 web 渗透测试 电子书 Python 黑客相关电子资源和书籍推荐 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/6952253.html,如需转载请自行联系原作者
原文链接:https://blogs.technet.microsoft.com/mmpc/2017/06/27/new-ransomware-old-techniques-petya-adds-worm-capabilities/?platform=hootsuite 未完全按原文翻译。 在2017年6月27日,一款勒索软件开始在欧洲大范围传播。我们注意到攻击从乌克兰开始,超过12,500台机器遭到威胁。随后勒索软件传播超过64个国家,包括比利时,德国,俄罗斯和美国。 这款新的勒索软件具备蠕虫特性,使得它可以通过网络对外传播。基于我们的研究,这款新的勒索软件是Ransom:Win32/Petya的一个变种,较之前的版本更加附加和强大。 为了保护用户,我们发布了更新补丁,用户可以到Malware Protection Center去下载。 0.1 传送和安装 最初的攻击起源于乌克兰的一家名为M.E.Doc的公司,微软根据相关证据证明勒索软件的下载安装使用了 “软件供应链攻击”方式。 我们检测到MEDoc软件的更新程序EzVit.exe执行了一个命令行命令,在6月27日10:30左右。下图演示了执行流程,但是EzVit.exe执行恶意命令的原因目前还未知。 Petya 0.2 单勒索软件,多方位传播技术 这个勒索软件,起初只感染了一台电脑,然后通过网络对外传播。它使用的到的基本技术包括: .窃取凭证或者重用当前会话\ .通过文件共享在内网传播恶意文件\ .通过合法途径执行负载,或者利用SMB漏洞(未打补丁的机器) 下面我们深入了解下这些技术的细节。 0.3 通过凭据窃取和身份伪造传播 勒索软件释放一个和Mimikatz类似的dumping工具(通常是放到%Temp%文件夹下的一个.tmp文件),区分32位和64位版本。因为用户通常使用具有本地管理员权限的账号登录电脑,并且和内网内多台机器保持通讯连接,被窃取的凭据很可能具有其他电脑上同样用户的访问级别。一旦勒索软件获取了有效的凭证,它会扫描局域网,并尝试通过139和445端口和其他电脑建立连接。对于域控制账号或者域服务器具有一个特殊的行为:勒索软件尝试调用 DhcpEnumSubnets() 方法,在扫描tcp/139 和 tcp/445端口之前,先枚举所有DHCP子网内的主机( to enumerate DCP subnets all hosts on all DHCP subnets before scanning for tcp/139 and tcp/445 services)。如果得到相应,勒索软件使用窃取到的凭据尝试向其他主机传输一个二进制文件,通过常规的文件传输方法。 之后它尝试通过PSEXEC 或WMIC 工具执行拷贝到远程主机上的恶意程序。 这个勒索软件试图从软件内嵌的资源中释放一个psexec.exe文件(通常会重命名为dllhost.dat)。然后它扫描局域网内admin$分享文件夹,通过网络拷贝自身到远程主机,并通过psexec.exe执行拷贝到远程主机的二进制文件。 为了凭据窃取,勒索软件尝试通过调用CredEnumerateW方法获取所有其他用户存储在机器上的凭据。如果一个凭据的名称以“TERMSRV/”开头并且类型设置为1,这个凭据会被用来在整个网络内传播。 Petya 勒索软件也使用Windows Management Instrumentation Command-line (WMIC)来寻找共享文件夹(NetEnum/NetAdd)从而传播自己。如果当前主机和远程主机存在链接,它会使用当前活跃链接的token进行数据传输,如果没有连接,会通过用户名密码的方式建立连接。 Petya 0.4 通过永恒之蓝( EternalBlue)和永恒浪漫(EternalRomance)传播 这款勒索软件也通过对 CVE-2017-0144 (also known as EternalBlue)的漏洞攻击直接传播。另外,它还使用第二个漏洞攻击CVE-2017-0145。 我们已经发现该勒索软件通过构造SMBv1数据包 全部是 XOR 0xCC 加密)来触发漏洞,代码分析如下: Petya Petya 这两个漏洞是Shadow Brokers泄漏出来的,微软已经在4月14日发布了补丁。用户可以通过安装补丁 security update MS17-010或者禁用SMBV1 来抵御此种类型的攻击。有关这两个漏洞的更多信息可以参考我们的博客。 0.5 加密 该勒索软件的加密行为依赖于它获取的权限和在目标机器上运行的进程的权限。它对进程名称进行简单的XOR-based 哈希,然后通过哈希值进行行为决策。 6.png .0x2E214B44-- 如果一个进程名的hash值是这个值的话,软件不会去感染MBR。 7.png .0x6403527E 或者 0x651B3005 -- 如果这两个hash值被发现,勒索软件不会进行任何网络活动(比如攻击SMBv1 漏洞) 8.png 如果没有异常情况,软件会向MBR写入启动数据,然后重启电脑。它建了一个定时任务,在至少十分钟后关闭电脑。实际时间是随机的 (GetTickCount())。例如: schtasks /Create /SC once /TN “” /TR “<system folder>\shutdown.exe /r /f” /ST 14:23 如果写入MBR成功,它会显示如下虚假的操作系统信息,提醒你设备错误,正在进行检查: Petya 然后会显示勒索信息: Petya ![Uploading 11_674996.png . . .] 只有在勒索软件获取足够高的权限的时候,它才会尝试覆盖MBR。 恶意软件尝试加密所有除C:\Windows文件夹之外的文件: Petya 它使用file mapping APIs 而不是常规的 ReadFile()/WriteFile() API来加密文件: Petya 和其他勒索软件不同,它没有添加一个新的文件扩展名到被加密的文件,而是覆盖了原文件。 它为每台机器生成一个AES秘钥,使用内置的 800-bit RSA公钥对其进行加密。 Petya Petya 唯一的用于加密的AES Key以加密的形式被添加到README.TXT文件中,写在 “Your personal installation key:”一节下面。 除了加密文件,这个勒索软件同时尝试重写MBR的第一个节——VBR。如果它以SeShutdownPrivilege 或者 SeDebugPrivilege 或者 SeTcbPrivilege权限运行,就会重写MBR,同时直接访问drive0 \\.\PhysicalDrive0。 MBR overwrite pseudo code: Petya Overwriting the first sector of VBR: Petya 加密之后,它释放一个 README.TXT文件: 17.png 最后勒索软件会清理 System, Setup, Security, Application event logs,删除NTFS 卷信息。 0.6 使用Windows Defender进行防御 无需安装更新,使用Windows Defender的高级防御功能就能进行防御.. (此处略过,感兴趣的可以查看原文) 0.7 通用防御措施 及时更新你系统。 尽量下载使用应用商店内的应用。 安装 MS17-010补丁。 如果未安装补丁,请按文档 Microsoft Knowledge Base Article 2696547 和recommended previously禁用SMBv1服务。 在路由器添加对445端口的阻止规则。关闭139和445端口,禁用远程WMI服务和文件共享。 最后还是推荐使用Windows Defender监控网络,企业用户使用Device Guard进行防御。 --- 0.jpg 关注玄魂工作室,更多教程,更多精彩 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/7092827.html,如需转载请自行联系原作者
Python 黑帽编程大纲(预览版) 教程说明: 本系列教程,采用的大纲母本为《Understanding Network Hacks Attack and Defense with Python》一书,为了解决很多同学对英文书的恐惧,解决看书之后实战过程中遇到的问题,教程采用重实践轻理论的风格来呈现。由于原书很多地方过于简略,笔者根据实际测试情况和最新的技术发展对内容做了大量的变更,当然最重要的是个人偏好。教程同时提供图文和视频教程两种方式,由于教程在创作过程中,在整套教程完结前,感兴趣的同学请关注我的微信订阅号(xuanhun521,下方二维码),我会第一时间在订阅号推送图文教程和视频教程。问题讨论,请加qq群:Hacking (1群):303242737 Hacking (2群):147098303。 图1 xuanhun521 微信订阅号 第一章 基于Kali Linux 2016 搭建开发环境 1.1 虚拟机安装和配置Kali Linux 2016 1.2 使用VSCode 搭建Python开发环境 1.3 Python运行时与包管理工具 1.4 你必须知道的网络基础理论——请自学 1.5 利用Wireshark练习数据包解析 第二章 Python语言基础 2.0 第二章概述 2.1 Python编程哲学 2.2 数值类型 2.3 字符串、列表、元组、映像和集合 2.4 流程控制 2.5 函数 2.6 模块 2.7 异常处理 2.8 套接字编程 2.9 面向对象编程 三章 主机到网络层攻击 3.0 第二层网络攻击基础知识 3.1 ARP欺骗 3.2 ARP监控 3.3 MAC洪水攻击 3.4 跨越VLAN 3.5 DTP攻击 第四章 网络互联层攻击 4.0 网络互连层攻击概述 4.1 Python黑帽编程 4.1 Sniffer(嗅探器)之数据捕获(上) 4.1 PYTHON黑帽编程 4.1 SNIFFER(嗅探器)之数据捕获(下) 4.2 Python 黑帽编程 4.2 Sniffer之数据本地存储和加载 4.3 嗅探密码 4.4 嗅探检测 4.5 IP投毒攻击 4.6 SYN洪水攻击 4.7 端口扫描 4.8 端口扫描检测 4.9 ICMP重定向 4.10 RST攻击 4.11 TCP劫持 4.12 工具推荐 第五章 DNS攻击 5.1 DNS协议 5.2 相关模块 5.3 WHOIS 5.4 DNS字典映射 5.5 DNS反向查询 5.6 DNS投毒 5.7 工具推荐 第6章 HTTP攻击 6.1 HTTP 协议 6.2 Web Services 6.3 相关模块 6.4 HTTP头提取 6.5 Referer 投毒 6.6 Cookie伪造 6.7 HTTP-Auth嗅探 6.8 Webserver扫描 6.9 SQL 注入 6.10 命令注入 6.11 xss跨站脚本攻击 6.12 SSL嗅探 6.13 代理扫描 6.14 代理端口扫描 6.15 工具推荐 第7章 WIFI攻击 7.1 wifi协议 7.2 相关模块 7.3 wifi扫描 7.4 wifi嗅探 7.5 探帧嗅探 7.6 寻找隐藏SSID 7.7 mac地址过滤 7.8 WEP 7.9 WPA 7.10 WPA2 7.11 Wifi数据包注入 7.12 Wifi客户端 7.13 死亡数据包 7.14 Wifi中间人攻击 7.15 无线入侵检测 7.16 推荐工具 第8章 蓝牙攻击 8.1 蓝牙协议 8.2 需要的模块 8.3 蓝牙扫描 8.4 SDP浏览 8.5 RFCOMM-Channel-Scanner 8.6 OBEX 8.7 攻击程序:Blue Snarf 8.8 攻击程序:Blue Bug 8.9 蓝牙投毒攻击 8.10 嗅探 8.11 推荐工具 第9章 综合实战 9.1 需要的模块 9.2 SMTP毒化攻击 9.3 DHCP劫持 9.4 IP风暴 9.5 Google-Hacks扫描 9.6 SMB共享扫描 9.7 web暴力登录监控 由于教程仍在创作过程中,在整套教程完结前,感兴趣的同学请关注我的微信订阅号(xuanhun521,下方二维码),我会第一时间在订阅号推送图文教程和视频教程。问题讨论请加qq群:Hacking (1群):303242737 Hacking (2群):147098303。 关注之后,回复请回复“Python”,获取更多内容。 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/p/5688350.html,如需转载请自行联系原作者
如果您需要编辑模板页,默认的FCK设置是会去掉<HTML></HTML><BODY> </BODY>标签,而且会给你加上<P></P>标签的,怎么办呢,只要设置一个小的 地方就可以了。在fckconfig里面有 FCKConfig.FullPage = false ; 改为 FCKConfig.FullPage = true 如果想去掉自动添加<P>的代码就可以在这里设置 默认是 FCKConfig.EnterMode = 'p' ; // p | div | br FCKConfig.ShiftEnterMode = 'br' ; // p | div | br 改成 FCKConfig.EnterMode = '' ; // p | div | br FCKConfig.ShiftEnterMode = 'br' ; // p | div | br 本文转自破狼博客园博客,原文链接:http://www.cnblogs.com/whitewolf/archive/2010/12/15/1906959.html,如需转载请自行联系原作者
mac 10.8上面,默认是没有svn客户端的,可以通过以下两种方式来安装: 1.单独安装xcode命令行工具,安装完成后,在终端中就可以使用svn命令了,目前版本是1.6.18; 2.去苹果官网上找svn源码编译安装。见http://www.apple.com/opensource/中的subversion,这个版本似乎还低一些。 其他的安装方式: 见http://subversion.apache.org/packages.html#osx 补充:mac 10.8上默认没有安装gcc,很悲催。 本文转自leipei博客园博客,原文链接:http://www.cnblogs.com/leipei2352/p/3254234.html,如需转载请自行联系原作者
一、依赖注入 1. 创建工程 ng new myangular 2. 创建组件 ng g componet product1 3. 创建服务 ng g service shared/product 如下图 4.服务的代码 product.service.ts 定义了一个Product类,并且在ProductService定义getProduct方法 6. product1.component.ts 中定义如下 7. 提供器声明 app.moudule.ts 8. 运行npm run start 结果如下 二、服务中使用其他服务 1. 创建logger服务 ng g service shared/logger 2. logger.service.ts logger服务中增加打印方法 3. 在Product中调用Logger服务 4. 在app.module.ts中添加提供器 5. 最终效果 三、工厂方法 每一次刷新可能会生成一种产品 2. 用具体的值来定义一个提供器 3. 对象作为提供器 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7246039.html,如需转载请自行联系原作者
1. /dev/null /dev/null相当于一个黑洞,写入它的数据将永远丢失.从它里面读取不到任何数据. 通常, /dev/null的作用是屏蔽shell的错误输出. ./myshell.sh 2> /dev/null 上面这条命令是执行自定义的shell.如果执行中有出错信息,则将出错信息重定向到/dev/null,这样就不会在屏幕上显示. 另外,还可以创建一个符号链接,将某个文件(例如上网时的广告文件)链接到/dev/null.这样,就不会在磁盘上保存了.2. /dev/zero 写入/dev/zero的内容会丢失.而从/dev/zero中读取出来的则是一连串的null(二进制的零流). /dev/zero的这个特性可以用来填充文件. 本文转自leipei博客园博客,原文链接:http://www.cnblogs.com/leipei2352/archive/2011/06/10/2077462.html,如需转载请自行联系原作者
Description Resource Path Location Type Error generating final archive: Debug Certificate expired on 12-5-26 下午10:50 HelloTest Unknown Android Packaging Problem 解决办法: 删除了主目录下的.android目录下debug.keystore和ddms.cfg. 本文转自leipei博客园博客,原文链接:http://www.cnblogs.com/leipei2352/archive/2012/08/11/2634133.html,如需转载请自行联系原作者
1.导入 1 2 3 4 import { Component, OnInit } from '@angular/core'; import {Observable} from 'rxjs/Observable'; import {Http, RequestOptions, Headers, URLSearchParams} from '@angular/http'; import 'rxjs/add/operator/map'; 2. 代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 clickPost() { const url = '接口地址'; const headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}); const d1 = new URLSearchParams(); d1.append('param1', 'param1' ); d1.append('param2', ' param2' ); d1.append('param3', 'param3' ); const options = new RequestOptions({ headers: headers }); this.http.post(url, d1, options ) .map(res => res.json()) .subscribe(function (data) { console.log(data); }); } 参考:https://stackoverflow.com/questions/35212341/angular2-http-post-request-parameters 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7340269.html,如需转载请自行联系原作者
Spring 3 MVC and XML example 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/5207407.html,如需转载请自行联系原作者
1.不要使用autowiring Spring可以通过类的自省来自动绑定其依赖部分,使得你不必明确指明bean的属性和构造器。Bean的属性可以通过属性名称或类型匹配来实现自动绑定。构造器通过类型匹配来实现自动绑定。你甚至可以指定自动检测自动绑定模式,它可以引导Spring选择一种适当的运行机制。先来看看下面的一个例子: class="com.lizjason.spring.OrderService" autowire="byName"/> OrderService类的属性名在容器中用于匹配bean实例。自动绑定可以潜在地节省一些打字和减少一些混乱。但是在现实世界的工程里你不应该使用这种方式,这是因为它牺牲了配置的清晰性和可维护性。许多指南和介绍中大量吹捧自动绑定是Spring的一种极好的特征而没有提到这一特性所带来的牺牲。依我的观点,这就像Spring中的object-pooling,它更像是一种为了占据更多市场的商业特征。它对于XML配置文件的小巧化是一个好办法,但实际上也增加了复杂程度,尤其当你运行有大量类声明的工程时。虽然Spring允许你混合自动绑定和手动绑定,但是这个矛盾会使XML配置更加晦涩难懂。 2.使用通俗的命名 这个方式对于Java编码也一样适用。在工程中使用清晰的、描述性的、协调的通俗名称对于开发者理解XML配置是十分有益的。例如对于beanID,你可以根据通俗的Java类名来命名它。对于例子中OrderServiceDAO的beanID命名为orderServiceDAO。对于大的工程,你可以在beanID前面加上包名作为前缀。 3.使用简洁的形式 简洁形式避免了冗长,是因为它从子元素中将属性值和参考写到属性中。例如下面的例子: class="com.lizjason.spring.OrderService"> lizjason 可以使用简洁形式将上述代码重写为: class="com.lizjason.spring.OrderService"> 简洁形式功能在1.2版本中可以使用。对于没有简洁形式。 简洁形式不但可以节约你的打字,而且可以使XML配置文件清晰。它最引人注目的是当在一个配置文件中有大量定义的类时可以提高易读性。 4.对于构造器参数匹配,类型名比序号好。 当一个构造器含有一个以上的同种类型的参数,或者属性值的标签已经被占用时,Spring允许你使用从0计数的序号来解决这些会带来混淆的问题。例如: class="com.lizjason.spring.BillingService"> 像下面这样,利用类型属性来编写会更好一些: class="com.lizjason.spring.BillingService"> value="lizjason"/> 使用索引可以稍稍减少一些冗长,但是和使用类型属性相比,它还是有容易发生错误的倾向和难于阅读的缺点。你应该只在构造器参数不明确的时候,才使用索引这一方法。 5.尽可能重用已定义过的bean Spring提供一种类似继承一样的机制来减少配置信息的复制并简化XML配置。定义一个子类可以从它父类那里继承配置信息,而父类实质上作为子类的一个模板。这就是大工程中所谓的重用。你所需要做的就是在父类bean中设置abstract=true,然后在子bean注明它自己的父类bean。例如: class="com.lizjason.spring.AbstractService"> parent="abstractService" class="com.lizjason.spring.ShippingService"> ShippingService类从abstractService类那里继承companyName属性的值??lizjason。如果你没有为一个bean指明类或factory方法,那么这个bean便是抽象的。 6.尽量使用ApplicationContext来装配定义的bean 像在Ant脚本中的引用一样,Spring的引用对于装配模块化的bean来说是很有用的。例如: class="com.lizjason.spring.OrderService"/> 相对于使用import在XML配置中来预装配,通过ApplicationContext来配置这些beans,显得更加灵活。利用ApplicationContext也使得XML配置易于管理。你可以像下面的例子那样在ApplictionContext构造器里布置bean: String[]serviceResources= {"orderServices.xml", "billingServices.xml", "shippingServices.xml"}; ApplicationContextorderServiceContext=new ClassPathXmlApplicationContext(serviceResources); 7.利用id作为bean的标识符 你可以指定一个id或名称来作为bean的标识符。虽然使用id不会提高易读性,但是它可以让XMLparser对bean的引用有效方面进行更好的验证。如果由于XMLIDREF的限制而不能使用某个id,你可以利用names来作为bean的标识符。XMLIDREF的限制是id必须以字母开头(或者在XML规范中定义的标点符号),后面接着字母,数字,连字号,下划线,冒号等。实际上,遇到XMLIDREF限制的问题是很少见的。 8.在开发阶段使用依赖检验 你可以在bean中给依赖检验的属性设置值,而不采用原先默认的空值,属性设置例如simple,object或all,以便容器进行依赖检验。当bean的全部的属性(或某类属性)需要被明确设置或自动绑定时,依赖检验便显得很有用。 class="com.lizjason.spring.OrderService" dependency-check="objects"> 在这个例子里,容器确保为orderServicebean设置的属性不是primitives或者collections。为所有的bean设置默认依赖检测也是可以的,但是我们很少这样做,是因为有些bean的属性根本就不必设置。 9.为每个配置文件加上一个headercomment 最好使用descriptiveid和名称来代替在XML配置文件中的注释。此外,加上一个配置文件header也很有用处,它可以概述文件中所定义的bean。你可以选择将描述内容加入description标签中。例如: Thisfiledefinesbillingservice relatedbeansanditdependson baseServices.xml,whichprovides servicebeantemplates... ... 使用description标签的一个好处是可以容易地利用工具从标签中选取出description(的内容)。 10.对于任何变化,要与队友积极交流 当你重构Java代码时,你需要随时更新配置文件并且通知队友。XML配置文件也是代码,它们是应用程序的至关重要的部分,但是它们难于阅读和维护。大部分时间你既要阅读XML配置文件又要阅读运行中的Java代码。 11.Setterinjection优于constructorinjection Spring提供3种类型的依赖注入:constructorinjection,setterinjection,和methodinjection。我们一般只用前两种类型。 class="com.lizjason.spring.OrderService"> class="com.lizjason.spring.BillingService"> 这个例子中,orderService类使用的是constructorinjection,而BillingService类使用的是setterinjection。constructorinjection可以确保bean不会在一个非法状态下被创建,但是setterinjection更加灵活并且更易管理,尤其当类存在很多属性并且其中一些是可选的情况下。 12.不要滥用依赖注入 作为最后一点,SpringApplicationContext可以替你创建Java对象,但是并不是所有的Java对象都通过依赖注入来创建的。例如,全局的对象不应该通过ApplicationContext来创建。Spring是一个很棒的框架,但是,就易读性和易管理性而言,当定义大量bean的时候,基于XML的配置问题就会突出。过度的依赖注入会使XML配置变得复杂而且臃肿。记住!使用强大的IDE时,例如Eclipse和IntelliJ,与XML文件相比,Java代码更加易读,易维护,易管理。 总结 对于Spring的配置,XML是很优秀的方式。但当定义大量bean时,基于XML配置会变得冗长,笨拙。Spring提供了丰富的配置选项。适当地利用其中的选项可以使XML配置清晰,但是,有些选项,例如autowiring(自动绑定),往往会降低易读性和易维护性。文章中所列举的实例,可以帮助你创建出清晰易读的XML配置文件。 本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2010/12/19/1910624.html,如需转载请自行联系原作者
一. 文件基本权限 1. - 文件类型,第一个字符为-,代表是文件类型(-文件 d目录 | 软链接文件) 2. 总共10个字符,2~10 总共9个字符,每三个字符为一组 rw- u所有者的权限 r-- g所属组的权限 r-- o其他人的权限 3. r 读 w 写 x执行 4. 上图中所有者为root,权限rw- 所属组为root, 权限为r-- 其他 权限为r-- 二、 修改权限 chmod命令 chmod [选项] 模式 文件名 选项 -R 递归 模式 [ugoa][+-=][rwx] [mode=421] 1. chmod u+x hello.txt 针对hello.txt 文件,给当前用户,增加x可执行权限 2. chmod g+x,o+x hello.txt 就是对所属组和其他增加写权限 3. 删除刚才增加的权限 命令为 chmod u-x,g-w,o-w hello.txt 4. chmod u=rwx hello.txt 修改当前用户的权限为rwx 5. chomd a=rw hello.txt 给所有人赋予rw权限 三、权限的数字表示 r ---- 4 w ---- 2 x ---- 1 rwx r-x r-x 7 5 5 如 chmod 755 hello.txt 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/8098131.html,如需转载请自行联系原作者
1. 修改文件的所有者 chown 用户名 文件名 2. 修改文件所属组 chgrp 组名 文件名 3. 创建用户,创建组,将用户添加到组中等 修改film文件夹的所有者和所属组 修改film文件夹的权限为 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/8099729.html,如需转载请自行联系原作者
1. 下载tomcat, http://apache.fayea.com/tomcat/tomcat-8/v8.5.16/bin/apache-tomcat-8.5.16.tar.gz 我下载的是这个版本 apache-tomcat-8.5.16.tar.gz 2. 放到CentOS对应的文件夹下 如:/home/server tar -zxv -f apache-tomcat-8.5.16.tar.gz // 解压压缩包 rm -rf apache-tomcat-8.5.16.tar.gz // 删除压缩包 mv apache-tomcat-8.5.16.tar.gz tomcat 3. 启动tomcat home/server/tomcat/bin/startup.sh 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7161888.html,如需转载请自行联系原作者
JS 继承的方式 1.使用call的方式 2. code如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script type="text/javascript"> //继承的第二种实现方式,call方法方式, Function对象中的方法 function test(str, str2) { alert(this.name + ", " + str + ", " + str2) } var object = new Object(); object.name = "zhangsanfeng"; //test.call相当于调用了test函数 test.call(object,"ssy","hello"); //将object赋值给this </script> </body> </html> 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7295192.html,如需转载请自行联系原作者
1. 创建工程 ng new demo3 2. 创建子组件 ng g component child 3. 在子组件中定义方法greeting 4. 父组件html(第三行是模板中调用子组件的方法) 5. 父组件Control调用子组件中的方法 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/p/7260266.html,如需转载请自行联系原作者
Immutable Collections(2)ImmutableList<T>实现原理.(上) 文/玄魂 前言 在上一篇文章(Immutable Collections(1)),我简要说明了不可变集合的基本概念和简单应用。从本篇博文开始,会探讨下几个典型集合类型的内部实现机制。本篇博客主要探讨ImmutableList<T>实现原理。 博文中引用的代码并非是.NET源码,而是反编译得来,不正确之处,还望指教。 2.1 概述 下图是ImmutableList<T>类型包含的核心字段、属性(并非全部),以及和其他类型的关系。这张图是自动生成的,我直接拿过来没有做什么改动,可能会让人云里雾里,下面我做简要的说明。 处于最顶端的ImmutableList静态类,是ImmutableList<T>类型的构造者,它或者直接返回ImmutableList<T>的Empty属性,或者在Empty的基础上构造ImmutableList<T>实例,比如下面的代码: public static ImmutableList<T> Create<T>() { return ImmutableList<T>.Empty; } public static ImmutableList<T> Create<T>(IEqualityComparer<T> equalityComparer) { return ImmutableList<T>.Empty.WithComparer(equalityComparer); } public static ImmutableList<T> Create<T>(T item) { return ImmutableList<T>.Empty.Add(item); } ImmutableList静态类下面是核心部分——ImmutableList<T>类型。ImmutableList<T>继承自如下接口: IImmutableList<T>, IReadOnlyList<T>, IReadOnlyCollection<T>, IList<T>, ICollection<T>, IList, ICollection, IOrderedCollection<T>, IEnumerable<T>, IEnumerable, IImmutableListQueries<T> 其中IImmutableList<T>定义如下: public interface IImmutableList<T> : IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable { IEqualityComparer<T> ValueComparer { get; } IImmutableList<T> Clear(); bool Contains(T value); int IndexOf(T value); IImmutableList<T> Add(T value); IImmutableList<T> AddRange(IEnumerable<T> items); IImmutableList<T> Insert(int index, T element); IImmutableList<T> InsertRange(int index, IEnumerable<T> items); IImmutableList<T> Remove(T value); IImmutableList<T> RemoveAll(Predicate<T> match); IImmutableList<T> RemoveRange(IEnumerable<T> items); IImmutableList<T> RemoveRange(int index, int count); IImmutableList<T> RemoveAt(int index); IImmutableList<T> SetItem(int index, T value); IImmutableList<T> Replace(T oldValue, T newValue); IImmutableList<T> WithComparer(IEqualityComparer<T> equalityComparer); } IImmutableListQueries<T>定义如下: internal interface IImmutableListQueries<T> { int Count { get; } ImmutableList<TOutput> ConvertAll<TOutput>(Func<T, TOutput> converter); void ForEach(Action<T> action); ImmutableList<T> GetRange(int index, int count); void CopyTo(T[] array); void CopyTo(T[] array, int arrayIndex); void CopyTo(int index, T[] array, int arrayIndex, int count); bool Exists(Predicate<T> match); T Find(Predicate<T> match); ImmutableList<T> FindAll(Predicate<T> match); int FindIndex(Predicate<T> match); int FindIndex(int startIndex, Predicate<T> match); int FindIndex(int startIndex, int count, Predicate<T> match); T FindLast(Predicate<T> match); int FindLastIndex(Predicate<T> match); int FindLastIndex(int startIndex, Predicate<T> match); int FindLastIndex(int startIndex, int count, Predicate<T> match); int IndexOf(T item); int IndexOf(T item, int index); int IndexOf(T item, int index, int count); int LastIndexOf(T item); int LastIndexOf(T item, int index); int LastIndexOf(T item, int index, int count); bool TrueForAll(Predicate<T> match); } 其他接口,是.NET中原有接口,这里就不列举了。IImmutableList<T> 的核心行为都定义在这两个接口当中。 SyncRoot是Object类型字段,作为同步锁对象。 Empty直接返回当前集合的单例对象EmptySingleton。 ImmutableList<T>构造函数如下: internal ImmutableList() { this.root = ImmutableList<T>.Node.EmptyNode; this.valueComparer = EqualityComparer<T>.Default; } private ImmutableList(ImmutableList<T>.Node root, IEqualityComparer<T> valueComparer) { root.Freeze(); this.root = root; this.valueComparer = valueComparer; } 在构造函数中我们又发现两个很重要的类型,Node和IEqualityComparer。IEqualityComparer这里就不解释了,我们重点关注Node,从字面上理解,这是一个表示节点的类,事实上它是ImmutableList<T>的核心,数据的承载和操作都是对Node类的包装。下面我们来看看Node的庐山真面目。 2.2 NODE Node类继承自三个接口, internal sealed class Node : IBinaryTree<T>, IEnumerable<T>, IEnumerable 我们主要关注IBinaryTree<T>,定义如下: interface IBinaryTree<out T> { int Height { get; } T Value { get; } IBinaryTree<T> Left { get; } IBinaryTree<T> Right { get; } bool IsEmpty { get; } int Count { get; } } 接口很清楚,定义了一个二叉树,但是这棵二叉树的具体特性但从接口上还无从得知。现在我们再看Node类。 ImmutableList<T>的EmptySingleton就是返回的上图中最上面的Node类的EmptyNode。EmptyNode定义如下: internal static readonly Node EmptyNode = new Node(); Node类的Key和Value属性是同一个值,就是当前节点的值。在代码中都是以Key为操作对象。下面分析Node的相关行为的时候,会有更清楚的认识。 frozen是一个bool类型的变量,表示是否冻结。冻结可以说是不可变集合的一个关键特性,下面也会对此做详细的分析。 height是以当前节点为根的树的高度。 this.height = 1 + Math.Max(left.height, right.height); count以当前节点为根的树的节点个数。 this.count = 1 + left.count + right.count; IsEmpty判断是否有子节点。 public bool IsEmpty { get { return this.left == null; } } right和left就是左右子树。 2.3 行为 2.3.1 初始化 我们通过下面的代码来观察Node的初始化过程。 static void Main(string[] args) { var fruitBasket = ImmutableList.Create<string>(); var ass = fruitBasket.Add("ddd"); } 启动程序,首先进入ImmutableList.Create<string>()方法。 Create方法直接返回ImmutableList<T>.Empty,Empty属性直接返回EmptySingleton。 调用EmptySingleton时触发ImmutableList<T>的初始化。 接下来在构造函数中调用Node.EmptyNode。 在Node类的无参构造函数中只初始化了一个变量: 此时Node.EmptyNode实例的各字段值如下图所示: 到此为止第一次初始化结束。 现在测试下带比较器的构造方式,先新建一个TestCompare类: class TestCompare<T> : IEqualityComparer<T> { public bool Equals(T x, T y) { return x.Equals(y); } public int GetHashCode(T obj) { return this.GetHashCode(); } } 然后更改Main函数中的代码: static void Main(string[] args) { var fruitBasket = ImmutableList.Create<string>(new TestCompare<string>()); var ass = fruitBasket.Add("ddd"); } ImmutableList静态方法仍然在ImmutableList<T>.Empty基础上调用了WithCompare方法。 WithCompare方法在初始化了valueCompare字段之后调用了构造函数ImmutableList(ImmutableList<T>.Node root, IEqualityComparer<T> valueComparer): private ImmutableList(ImmutableList<T>.Node root, IEqualityComparer<T> valueComparer) { Requires.NotNull<ImmutableList<T>.Node>(root, "root"); Requires.NotNull<IEqualityComparer<T>>(valueComparer, "valueComparer"); root.Freeze(); this.root = root; this.valueComparer = valueComparer; } 上面的构造函数,调用了Freeze()方法, internal void Freeze() { if (!this.frozen) { this.left.Freeze(); this.right.Freeze(); this.frozen = true; } } 这段代码,实际上是一个递归调用,设置每个节点为冻结状态。 带初始值的构造函数,实际是调用了Add方法,我将在下一篇博文中单独分析。 本篇博文到此结束,未完,待续。。。。。。 本文转自玄魂博客园博客,原文链接:http://www.cnblogs.com/xuanhun/archive/2013/05/06/3063787.html,如需转载请自行联系原作者