SegmentFault SoulReaper最新的文章
2017-06-25T09:23:42+08:00
https://segmentfault.com/feeds/blogs
https://creativecommons.org/licenses/by-nc-nd/4.0/
Mac下安装apache waf模块modsecurity
https://segmentfault.com/a/1190000009918653
2017-06-25T09:23:42+08:00
2017-06-25T09:23:42+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
0
<h2>modsecurity简介</h2>
<p><strong> mods 是apache的一个安全模块,他的作用是web应用防火墙(WAF).如果不懂WAF请自行google下。</strong></p>
<h2>问题的由来</h2>
<p><strong> mods在yum源(centos)以及apt源(ubuntu)下都有现成的安装包。只需要类似 apt-get install 或者yum install 即可。</strong><br><strong> 但是在mac的osx系统下,没有任何二级制安装包,如果想在osx上玩mods,那就需要从源码编译</strong></p>
<h2>源码编译</h2>
<p><strong> 一般来说,一条命令就可以搞定。谁让brew很逆天呢</strong>。<br>命令如下:</p>
<pre><code>brew install homebrew/apache/mod_security</code></pre>
<blockquote><p>参考:<a href="https://gist.github.com/amarnus/621fc1612036e186b6a6">https://gist.github.com/amarn...</a></p></blockquote>
<p>如果顺利的话,brew会下载所有依赖以及mods的源码进行编译安装。但是....貌似一般不会那么顺利。</p>
<h2>编译时问题</h2>
<h6>1. brew安装时,在写入usr等文件夹的时候会说没有权限。加上sudo 或者sudo -i切换到root再安装的时候,又会说『使用root权限安装太危险了』....黑人问号脸,你特么在逗我,那你说该怎么装嘛..</h6>
<p><strong> 解决方案: sudo chown ${whoami} /usr 直接暴力把/usr的归属给变成了当前用户..哪位大佬有其他方案请分享出来</strong></p>
<h6>2. 下载mods包的时候一直没进度(是curl抽风了好么)</h6>
<p><strong>解决方案:</strong></p>
<ol>
<li><p>brew会显示从那个url下载该源码包。复制url,浏览器下载</p></li>
<li><p>然后执行brew --cache看看cache目录在哪里</p></li>
<li><p>把下载下来的压缩包丢到该目录下面(奇怪的是我这边显示出来的cache目录不是显示出来的cache目录,大家可以往/Users/xxx/Library/Caches/Homebrew/放一份再)</p></li>
</ol>
<h6>3. 安装到最后的提示没有apu或者apr库</h6>
<p>这个有点麻烦,理论上brew会帮忙装好的。但是我看日志好像是mods的makefile指定的apr/apu的目录有问题,修改makefile有点麻烦,又不知道brew把apr和apu装到哪里去了。所以自己下载apr和apu的安装包,再编译了一遍,然后./configration的时候通过参数指定路径。参考</p>
<blockquote><p><a href="https://link.segmentfault.com/?enc=D2XALVJbBYQn8smAB8roMg%3D%3D.Fnu0ufVPEtBmajn1NvPFW8qOAKF%2Ba8yy5ySjNJHZObluXn8rkOBAMlH8zV%2F6%2B%2BxKv3dO1d4sFtRuz5ADZ1aEKQ%3D%3D" rel="nofollow">http://blog.csdn.net/nyist327...</a></p></blockquote>
<h6>4. 要安装xcode,并且升级到最新版本</h6>
<h6>5. 安装的时候会提示xcode commond tool没有安装,然后给你一个命令,你要运行一下安装程序,然后要重启下机器</h6>
<pre><code>xcode-select --install</code></pre>
<h6>6. 如果没有关闭Rootless机制,会报错opration not premitted</h6>
<p>我之前就关闭了,虽然是一个不错的安全策略,但是对开发者很不方便。<br>具体关闭步骤:</p>
<ol>
<li><p>重启机器,在启动的时候长按command+R,进入恢复模式</p></li>
<li><p>打开terminal,执行</p></li>
</ol>
<pre><code>csrutil disable</code></pre>
<ol><li><p>重启机器到正常模式</p></li></ol>
<h6>7. 如果还是编译失败,你可以把下载下来的mods的包解压,然后自己编译(反正我是成功了)</h6>
<p>编译方式如下:(请使用sudo -i 切换到root用户下)</p>
<h6>进行configration</h6>
<pre><code>./configure --prefix=/usr/local/Cellar/mod_security/2.9.1 --with-pcre=/usr/local/opt/pcre --with-apxs=/usr/sbin/apxs --with-apr=/usr/local/apr/bin/apr-1-config --with-apu=/usr/local/apr/bin/apu-1-config </code></pre>
<h6>make</h6>
<pre><code>在解压目录下执行 make</code></pre>
<h6>make install</h6>
<pre><code>在解压目录下执行 make install</code></pre>
<h2>检查是否编译成功并配置</h2>
<ul>
<li><p>请检查<code>/usr/local/Cellar/mod_security/2.9.1/lib</code>下是否有<code>mod_security2.so</code>,若有则标识编译成功</p></li>
<li><p>进行模块配置</p></li>
</ul>
<pre><code>1. vim /etc/apache2/httpd.conf
2. 配置载入模块:
LoadModule security2_module /usr/local/Cellar/mod_security/2.9.1/lib/mod_security2.so
3. 从源码目录复制配置文件到指定文件夹
cp modsecurity.conf-recommended /etc/apache2/other/modsecurity.conf</code></pre>
<h2>启动apache</h2>
<pre><code>sudo apachectl start</code></pre>
<h2>规则怎么配就靠你玩了,收工</h2>
安卓渗透框架-Drozer架构浅析--架构组成和自定义模块
https://segmentfault.com/a/1190000003756601
2015-09-16T23:46:06+08:00
2015-09-16T23:46:06+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
0
<h2>安卓渗透框架-Drozer架构浅析--架构组成和自定义模块</h2>
<p>标签(空格分隔): Drozer Android Security</p>
<hr>
<h2>1. Drozer 简介</h2>
<blockquote><p><strong><em>Drozer</em></strong>是MWR Labs开发的一款针对Android系统的安全测试框架。Drozer可以通过与Dalivik 虚拟机,以及其它应用程序的IPC端点以及底层操作系统的交互,避免正处于开发阶段,或者部署于你的组织的android应用程序和设备暴露出不可接受的安全风险。</p></blockquote>
<hr>
<h2>2. Drozer的使用</h2>
<p>网上关于Drozer如何使用的文章很多,这里贴出来一两篇比较好的:<br>中文版:<a href="https://link.segmentfault.com/?enc=UuiKCpjUwjsWPr1leKzWCA%3D%3D.93nG0tAzSF8BPT7jxIf1t70ehiu6AMTNgvJC1rKkWCLqApolZmQtg5MN1uEZqhsP" rel="nofollow">http://www.freebuf.com/tools/26503.html</a><br>英文版:<a href="https://link.segmentfault.com/?enc=W0f9Yf9BJo3FKYbHqMSiZw%3D%3D.sRMvrYFebKgqkxHbvxwrqi8dN6qiajezsKoWytp4B%2FLJDtTaL5e%2Fdjg%2FNq1Ad2gYn3dG5xjqxYG%2BZKl5tyraIo1%2FpysnbCxIMyW327kGkW7EV4J%2F9J2fahYPdXJGK%2BLuNYmHhv%2BmYHv1mrsiaaNAmA%3D%3D" rel="nofollow">https://www.mwrinfosecurity.com/system/assets/937/original/mwri_drozer-user-guide_2015-03-23.pdf</a></p>
<hr>
<h2>3. Drozer 组成</h2>
<h4>Drozer 总共由以下几个部分组成:</h4>
<ol>
<li><p><strong>Drozer Console</strong> ---- Drozer 的pc端用户操作接口</p></li>
<li><p><strong>Drozer agent</strong> ---- 安装在安卓手机上的Drozer代理应用</p></li>
<li><p><strong>Drozer Modules</strong> ---- Drozer所包含的可以被利用的模块,Exploit,Payload</p></li>
<li><p><strong>Drozer API</strong> ---- Drozer提供的 customize module 接口,用来编写自定义module或者exploit,payload</p></li>
<li><p><strong>Drozer Common</strong> ---- 在console和agent之间传输和共享数据的一些组件</p></li>
<li><p><strong>Other:</strong> (optional)<br> ----------<code>Rogue agent</code>:提供了远程管理工具的代理<br> ----------<code>JAR agent</code>:对<code>Rogue agent</code>进行了jar打包<br> ----------<code>Weasel</code>: 可以理解为提供的和<code>Rogue agent</code>配套的高级payload</p></li>
</ol>
<hr>
<h2>4. Drozer Console</h2>
<p>Drozer Console 是用python编写而成的一个命令行工具,使用者可以通过console连接到agent上对Dalvik VM 进行操作。</p>
<blockquote><p>接口是通过python的官方模块<code>cmd</code>和<code>readline</code>等模块实现,通过<code>shlex</code>解析命令,通过<code>argparse</code>解析参数。感兴趣的可以阅读Drzer Console的相关源码:</p></blockquote>
<p>github地址:<a href="https://link.segmentfault.com/?enc=dPVsoNX806Cr9nPWCU9P3A%3D%3D.fKHPf3hQefxiR%2F8NA%2FwahwpJBnZfJYpS6XyaTfXpcGrrrH%2BOnE0vfde4zwUvyVkl" rel="nofollow">https://github.com/mwrlabs/drozer</a></p>
<hr>
<h2>5. agent</h2>
<p>agent 是一个安装在测试安卓机上轻量级app,并且只申请一个权限,是为了用来和pc进行连接的。这个agent应用要求 Android API leven 7,兼容于Andriod 2.1以及以上的版本</p>
<h3>(1) agent和console的连接方式</h3>
<h4>1. 直连方式(Direct Mode):</h4>
<p>这一种链接方式,是需要在pc机上安装<code>adb</code>工具,并且使用数据线将测试机链接在pc机上实现的,agent会在测试机上开启一个服务器,然后通过adb开启一个本地tcp通路:<br><code> adb forward tcp:31415 tcp:31415</code><br>这样就可以连接上agent的服务器了。具体操作请看使用教程。</p>
<h4>2. 网络链接方式(Infrastructure Mode):</h4>
<p>这种方式是用过局域网去链接的,pc机开启一个server,然后在agent上配置和server建立tcp链接,再使用终端链接上去。具体请查看使用教程。</p>
<h3>(2) 具体连接形式(connections)</h3>
<p>drozer 的connections是通过一种通用的二进制消息传输形式(protobuf,具体请查看google的protobuf开源项目)来传输Frame信息,在console端是一个python的线程,在agent端是java的一个线程,他们传输的消息有以下几种:</p>
<p><strong>1. 如果是SYSTEM_REQUEST,就传输的是SystemMessageHandler消息,SYSTEM_REQUEST指的是agent和console之间进行连接,交换状态的消息,她可以分为两种,<code>SystemRequest</code>和<code>SystemResponse</code></strong></p>
<p><strong>2. 如果是REFLECTION_REQUEST,就传输的是 ReflectionRequestHandler消息,REFLECTION_REQUEST指的是用户在使用相关的exploit或者payload命令的时候传输的消息,也有两种:<code>ReflectionRequest</code>和<code>ReflectionResponse</code></strong></p>
<p>agent源码:<a href="https://link.segmentfault.com/?enc=EUuaZNkwoO9Iu%2BU0S4ZfRA%3D%3D.KKsUDPIRGWrUkQc2uWP1Zz4eg%2BdQa1qLzvVj9ZXR24Ml0%2FruOe0WwckDbF4UdjQV" rel="nofollow">https://github.com/mwrlabs/drozer-agent</a><br>传输消息格式和类型:<a href="https://link.segmentfault.com/?enc=Ck4%2FnnjnGd8lYolLjYL2tw%3D%3D.ngvlhcCTmJdzYyxR%2FLhyNvpgN8Hd0HZNQHglBptmZogGW9tV7RoFj2yNor62p2JZ" rel="nofollow">https://github.com/mwrlabs/mercury-common</a></p>
<h3>(3) 消息传输session</h3>
<p>和http一样,drozer的console和agent之间的传输也有session,当console和angent链接成功的时候,agent便会生成一个session,它是一个256位的hash字符串,后面的每一次通信都必须带上该session id</p>
<hr>
<h2>Drozer Modules</h2>
<p>drozer拥有很多可以直接利用的Module, Exploit, Payload.这些你可以在drozer console中使用<code>list</code>命令查看相关module,也可以在bash下使用<code>drozer exploit list</code>查看相关exploit,也可以使用<code>drozer payload list</code> 来查看相关payload。具体使用方式请查看相关帮助。</p>
<p>所有的module源码可以在这里查看:<br><a href="https://link.segmentfault.com/?enc=zHbvX9MGlMxZOGo4y%2FyOrQ%3D%3D.GUnq%2BSQJJ3Iv33nvs3h1g7ql9PlI0YoM3u%2BWV1fhocPb8GQ4ygorZEYsa7SKl8zJ" rel="nofollow">https://github.com/mwrlabs/drozer-modules</a></p>
<hr>
<h2>Drozer API</h2>
<p>Drozer 提供了module编写接口,在安装好drozer之后,就可以使用python来用相关的库了.<br>相关可以查看官方文档和相关博客:</p>
<ol>
<li><p><a href="https://link.segmentfault.com/?enc=uVimRWbru4rfCBAgx1u%2BtA%3D%3D.e%2BmehfY0psiNIGADJIuatXy%2BFrys9bpKEbLxXNw6F85TjXaG31Y%2BBxhZQ5NFWNauYEMYcOPbfuY5Nd0aYx0vTg%3D%3D" rel="nofollow">https://github.com/mwrlabs/drozer/wiki/Writing-a-Module</a></p></li>
<li><p><a href="https://link.segmentfault.com/?enc=ugdcF62WxErnO8nJ7nf0gQ%3D%3D.9LJto3V9ptwERP4TguuFTMJZP1isNNjRJvpWhmhMnchjs1lOOR2XukVxeg89BRg7" rel="nofollow">http://appscan.360.cn/blog/?p=45</a></p></li>
</ol>
Django 安全配置(setting.py)详解
https://segmentfault.com/a/1190000003756582
2015-09-16T23:44:19+08:00
2015-09-16T23:44:19+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
8
<h2>Django 安全配置(setting.py)详解</h2>
<p>标签(空格分隔): python django web安全</p>
<h3>---</h3>
<h3>1. 必须配置:</h3>
<h4><strong>0x01. PASSWORD_HASHER</strong></h4>
<p>这个配置是在使用<code>Django</code>自带的密码加密函数的时候会使用的加密算法的列表.默认如下:</p>
<pre><code>PASSWORD_HASHERS = (
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
)</code></pre>
<p>默认使用第一个条目的加密算法,即<code>PBKDF2</code>算法.<br>所以在使用<code>make_password</code>,<code>check_password</code>,<code>is_password_unable</code>等密码加解密函数的时候,需要添加这个list在<code>setting.py</code>文件中,推荐使用默认配置的算法.<br><strong>相关链接</strong>:<br><a href="https://link.segmentfault.com/?enc=a4u3tiKWUqTA68sNzizlWQ%3D%3D.mrwZIbafUx4WZaNybPAp5aUCnMptxbAfNDbOJ4Gw2mP6UWlZTP0dLB6OBeCzuYK21sS6jvLcHHCsDCx0oJI%2BDpGo4JiKDI8pxRMG2tJU2h0%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/settings/#password-hashers</a><br><a href="https://link.segmentfault.com/?enc=v26Pug0qXuQ1%2FwTEvtSKjg%3D%3D.yBtukDGVyx0AfsDi2RNuKlbrWsZEWH8RGlo%2BVHSHMCv%2FEed%2FudGX0yjvVAmfAWDMZbTWugAfYGPRMpJItnGZZA%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/topics/auth/passwords/</a></p>
<hr>
<h4><strong>0x02. ADMINS</strong></h4>
<p><code>ADMINS</code>是一个二元元组,记录开发人员的姓名和email,当DEBUG为False而views发生异常的时候发email通知这些开发人员.类如:</p>
<pre><code>(('John', 'john@example.com'), ('Mary', 'mary@example.com'))</code></pre>
<p><strong>相关链接:</strong><br><a href="https://link.segmentfault.com/?enc=iihN8nR0cmnAYh7EfDQABg%3D%3D.3omSiK6W2ETs1MtP5YQj4zpBfLZg4heBWE9sQN5TiTwJu14YhzYVHm%2F5pfME2V4eqm9K5DMV2zGOeI%2Bo0ku5ig%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/settings/#admins</a></p>
<hr>
<h4><strong>0x03. ALLOWED_HOSTS</strong></h4>
<p><code>ALLOWED_HOSTS</code>是为了限定请求中的host值,以防止黑客构造包来发送请求.只有在列表中的host才能访问.强烈建议不要使用<code>*</code>通配符去配置,另外当<code>DEBUG</code>设置为<code>False</code>的时候必须配置这个配置.否则会抛出异常.配置模板如下:</p>
<pre><code>ALLOWED_HOSTS = [
'.example.com', # Allow domain and subdomains
'.example.com.', # Also allow FQDN and subdomains
]</code></pre>
<p><strong>相关链接:</strong><br><a href="https://link.segmentfault.com/?enc=tLmGJ6thWzoaW3gYtnnBBg%3D%3D.Q2Kor%2FVaoOzzyj44Ne20AOvzHUBCd76mJIZG6CdW1DoaVW3CW0IOBtSeeYNBfwXBzxni0MeD1krFEvVQSJ7rt%2BT98bQ%2B4ZKqh3W6LmIqs6c%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/settings/#allowed-hosts</a></p>
<hr>
<h4><strong>0x04. DEBUG</strong></h4>
<p><code>DEBUG</code>配置为<code>True</code>的时候会暴露出一些出错信息或者配置信息以方便调试.但是在上线的时候应该将其关掉,防止配置信息或者敏感出错信息泄露.</p>
<pre><code> DEBUG = False</code></pre>
<p><strong>相关链接:</strong><br><a href="https://link.segmentfault.com/?enc=ty3nXJFPaVMGMdmjNmAgXg%3D%3D.cRwrTjaZE%2F5tu6iAIu7a6aOfyNYpPwMD6rUkDZlx3ELdLgCsh3ajzwuTaWlf8AtU9GZN9eGSxwYmpw2KN2cliA%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/settings/#std</a>:setting-DEBUG</p>
<hr>
<h4><strong>0x05. INSTALLED_APPS</strong></h4>
<p><code>INSTALLED_APPS</code>是一个一元数组.里面是应用中要加载的自带或者自己定制的app包路径列表.</p>
<pre><code>INSTALLED_APPS = [
'anthology.apps.GypsyJazzConfig',
# ...
]</code></pre>
<p><strong>相关链接:</strong><br><a href="https://link.segmentfault.com/?enc=uni2BKSGv5sfv7h%2BiBuQvA%3D%3D.t%2BHfoPdaATRmYPdU1NBBsBuP%2B1xqk9mu1etLxk1onA2GMDDCP1QRo%2FyQbCAAJ1klyB37VKJ24xMBNGV7%2FluS4os8BISYLeWHnu%2FZLHvgBKk%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/settings/#installed-apps</a><br><a href="https://link.segmentfault.com/?enc=9djKNhGFgYlVHtuMySOUjA%3D%3D.Y7fVSmngdlXLR%2BtjiyrLkb4ChFagl2MVzdckj6xQzRvFUpuI3xA8XM%2FpWfFfXhvZHv2fiakXYexJAI0xKluggA%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/applications/</a></p>
<hr>
<h4><strong>0x06. MANAGERS</strong></h4>
<p>和<code>ADMINS</code>类似,并且结构一样,当出现'broken link'的时候给manager发邮件.<br><strong>相关链接:</strong><br><a href="https://link.segmentfault.com/?enc=XVH4%2FLF9Sgq2MDUbLkoJgw%3D%3D.kmFS%2BVfjaipIoS7KWEG%2Bmc8aXgY2a4vDrryPyazvKl54EdXJUSWy2K4Vkvc6L%2Bkctmp7hbh%2BifDiMGjp1iOJ3g%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/settings/#std</a>:setting-MANAGERS</p>
<hr>
<h4><strong>0x07. MIDDLEWARE_CLASSES</strong></h4>
<p>web应用中需要加载的一些中间件列表.是一个一元数组.里面是django自带的或者定制的中间件包路径,如下:</p>
<pre><code>MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)</code></pre>
<p><strong>相关链接:</strong><br><a href="https://link.segmentfault.com/?enc=hz4xJ%2BeSQdqojRFYLGZQyQ%3D%3D.kwnqoogr15%2FlSawNmeXBESQH90CYQFxyjT7Dm9UEDyMb7cvoSOCMYco0lhZDfFi4S0R7Pcxoy23tQJcJtYnteA%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/settings/#std</a>:setting-MIDDLEWARE_CLASSES<br><a href="https://link.segmentfault.com/?enc=RsXMXQ54BNqfM4VtASwV0g%3D%3D.qnBQmVBVw5TmyF0adDxfSfYNSsGW5d9%2Fc0YvqhHCB4nbacCZDJQNaDDxYIzEZNQ1qoKKRACJHiUdPw7g6ETgog%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/topics/http/middleware/</a></p>
<hr>
<h4><strong>0x08. TEMPLATE_DEBUG</strong></h4>
<p>同样是一个DEBUG开关,若为<code>True</code>,DEBUG信息在触发异常之后,会显示在网页上.上线之前必须修改成:</p>
<pre><code>TEMPLATE_DEBUG = False</code></pre>
<p><strong>相关链接:</strong><br><a href="https://link.segmentfault.com/?enc=1fSP99Uh3xGIdIBZXT8GYA%3D%3D.NOg1%2B0MrHBFQpAPH5sfo8gNV6SODlrCxcdtu7Si7c%2BnUNdJx8S3lzz8YtuFUhE38qUzuoBeT2rqk%2BYrUIxqIhg%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/settings/#std</a>:setting-TEMPLATE_DEBUG</p>
<hr>
<hr>
<h3>2. 建议配置</h3>
<hr>
<h4><strong>0x01. DEBUG</strong></h4>
<pre><code>DEBUG = False</code></pre>
<p>防止配置信息和调试信息暴露</p>
<hr>
<h4><strong>0x02. SESSION_COOKIE_SECURE</strong></h4>
<pre><code>SESSION_COOKIE_SECURE = True</code></pre>
<p>使得<code>session cookie</code>被标记上<code>secure</code>标记,从而只能传输在<code>HTTPS</code>下<br><strong>相关链接:</strong><br><a href="https://link.segmentfault.com/?enc=gg19iYiCYdocYKmaZJq02w%3D%3D.uLI0S9Be3OhLYvhULY667V3fGT%2BZCZrNsOeii1FTRlIjaXv%2Bwn%2FudFOxrfwojHis%2Fh%2BkrBdw%2Bsq6f2Rbcn0mtUAzf3RssSvU8dP6Ij56y%2FY%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/settings/#session-cookie-secure</a></p>
<hr>
<h4><strong>0x03. SESSION_COOKIE_HTTPONLY</strong></h4>
<pre><code>SESSION_COOKIE_HTTPONLY = True</code></pre>
<p>使得<code>session cookie</code>被标记上<code>http only</code>标记,从而只能被http协议读取,不能被<code>Javascript</code>读取</p>
<hr>
<h4><strong>0x04. TEMPLATE_DEBUG</strong></h4>
<pre><code>TEMPLATE_DEBUG = False</code></pre>
<p>防止配置信息和debug信息通过view传出.</p>
<hr>
<hr>
<h3>3. 推荐的中间件:</h3>
<hr>
<h4><strong>0x01. SessionMiddleware</strong></h4>
<ol>
<li><p>配置作用:<br>在应用中使用session</p></li>
<li><p>配置方法:<br>在MIDDLEWARE_CLASSES中加入:<br><code>django.contrib.sessions.middleware.SessionMiddleware</code></p></li>
<li><p>相关链接:<br><a href="https://link.segmentfault.com/?enc=S8sG3XGjxS%2FyfYL8Ei%2FGPg%3D%3D.fdXArXOE6wwXWWN4tNiT1l2S7mZGzeEWZ8LkpWMyz%2FTV6ILQXfnrPbamBZOV%2FlAjDGBPJM0AJbcECeX3WlIHYQ%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/middleware/</a><br><a href="https://link.segmentfault.com/?enc=DExOK33cg%2FSsfGzlSwpHaw%3D%3D.74bY8kv2v2I1%2FlyOO4Y2wxJ9RnGCioLLBBUiOXe3NEperLW%2F2Js5b06anmgCDXnDNrnLDy9LkmNM6zuw4M0QvQ%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/topics/http/sessions/</a></p></li>
</ol>
<hr>
<h4><strong>0x02. CsrfViewMiddleware</strong></h4>
<ol><li><p>配置作用:<br>在应用中添加CSRF token用来防范csrf攻击</p></li></ol>
<ul><li><p>配置方法:</p></li></ul>
<ol>
<li><p>1.在MIDDLEWARE_CLASSES中加入:<br><code>django.contrib.sessions.middleware.CsrfViewMiddleware</code></p></li>
<li><p>相关链接:<br><a href="https://link.segmentfault.com/?enc=8vAVtaCfQdB0WVvok0x3jQ%3D%3D.pqsUQZpzz8R46wYiDvKsyuA%2BHd0bnhaimo4pTA5r8aqR8%2FeHogNu7CoQt9%2FLBBRmFunKW5ojDeovYXZU6s%2Bx0A%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/middleware/</a><br><a href="https://link.segmentfault.com/?enc=YQZnMI8XHR94lDdwbmaFRg%3D%3D.nA2%2FbQth5Wo4HPJNmgm5%2Bz9d4bDllUJ876myJB7eFL3gR25lIC%2B8VKB3c5tSR9ca" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/csrf/</a></p></li>
</ol>
<h4><strong>0x03. clickjacking.XFrameOptionsMiddleware</strong></h4>
<ol><li><p>配置作用:<br>在Http header中添加 <code>X-Frame-Options</code> 标志.防范Clickjacking</p></li></ol>
<ul><li><p>配置方法:</p></li></ul>
<ol>
<li><p>1.在MIDDLEWARE_CLASSES中加入:<br><code>django.middleware.clickjacking.XFrameOptionsMiddleware</code></p></li>
<li><p>相关链接:<br><a href="https://link.segmentfault.com/?enc=0DpUU%2BFFhS8Stxp6hMnFUg%3D%3D.U0T7tMVoyfeYfbo5JFGIVdfcP7D18dVCHxVK1kg6CqA8rgiEzS%2FcjI2FrpWRkgP%2Bc%2F0djRfW2jQPP9%2BhsOqEjw%3D%3D" rel="nofollow">https://docs.djangoproject.com/en/1.8/ref/clickjacking/</a></p></li>
</ol>
<hr>
<hr>
<h3>4. 推荐安装的app:</h3>
<hr>
<h4><strong>0x01. django_bleach</strong></h4>
<p>作用:过滤html字符串,返回合法的已经过滤的安全html字符串.<br>官方链接:<a href="https://link.segmentfault.com/?enc=M2sdu52xnh2upkswl1XgUA%3D%3D.%2BFwQN0bsh87oxjoolbAawqZaH1iECrhHTeBOyfpvIHZc8Q8hDtYJzRqaHrMJ1sSd" rel="nofollow">https://bitbucket.org/ionata/django-bleach</a><br>文档:<a href="https://link.segmentfault.com/?enc=8GfezwgcRlZcB4WsP%2B826A%3D%3D.mxXi1VROKvgpKvB97kKjhvDKNSlHbCo%2FEiJywrk%2BYYdUSnA79g%2BJAL2K17AHuc6gF5ScXAdY2XyGsi7HaHIiFQ%3D%3D" rel="nofollow">https://django-bleach.readthedocs.org/en/latest/</a></p>
<h4><strong>0x02. xframeoptions</strong></h4>
<p>作用:防范ClickJacking,作用和官方的XFrameOptionsMiddleware相似<br>官方链接:<a href="https://link.segmentfault.com/?enc=IsqUAakaHx8I4qj7Mw4kHQ%3D%3D.sS9v%2B3%2FbLMbbGjXoGUX%2BboyW0SzYsAyBcYLpcljB%2BeKByVb9WIG%2BX4M%2FyktMlCH2XIcZ3UNJI4e7KPmwRvriAw%3D%3D" rel="nofollow">https://github.com/paulosman/django-xframeoptions</a></p>
HTML5 安全问题解析
https://segmentfault.com/a/1190000003756563
2015-09-16T23:42:28+08:00
2015-09-16T23:42:28+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
3
<h2>HTML5 安全问题解析</h2>
<p>标签: html html5 web安全</p>
<h3>本文参考:</h3>
<ol>
<li><p>w3school:html5相关基础知识(w3school.com.cn)</p></li>
<li><p>51CTO的HTML5安全专题</p></li>
<li><p>FREEBUFF上有关HTML5的安全文章(FREEBUFF搜索关键词:html5)</p></li>
<li><p>相关技术博客和杂文(百度搜索关键词:html5 安全)</p></li>
</ol>
<hr>
<h3>文章概要:</h3>
<ol>
<li><p>html5相关新技术</p></li>
<li><p>跨域资源共享(CORS)安全问题</p></li>
<li><p>本地数据库注入(Web Sql Injection)</p></li>
<li><p>本地存储风险(Local Storage and Session Storage)</p></li>
<li><p>js多线程(Web Worker)风险</p></li>
<li><p>Web Socket带来的嗅探风险</p></li>
<li><p>新标签风险</p></li>
<li><p>新API风险</p></li>
</ol>
<hr>
<h3>正文:</h3>
<hr>
<h3>0x01 html5相关新技术</h3>
<h4><strong>1. XMLHttpRequest Level 2 (CORS)</strong></h4>
<p>XMLHttpRequest主要提供了js直接发送请求的接口,在老版本中有以下缺点:</p>
<ul>
<li><p>只能支持文本数据传送,其他数据不可</p></li>
<li><p>没有即时进度信息,只有完成与否的状态</p></li>
<li><p><strong><em>不能跨域传输,只能同域内进行传输</em></strong></p></li>
</ul>
<p>在新版本的XMLHttpRequest中(level 2),以上都得到了实现,其中最关键的是可以在服务器和浏览器本身的支持下进行跨域传输。</p>
<p><a href="https://link.segmentfault.com/?enc=pu1g9usseazXx3E3cux4iQ%3D%3D.nJbkbz5N17s%2BwvYwCeDA%2FkoAwjeaDgqpeubzIJqS9ZhwFX5QIk9uwtR%2Bfyyo24xsjOAqmzsr7hXaQrYpRIWfJ%2FOnPgSo02JkQ53VHHtn6Dw%3D" rel="nofollow">具体细节请参考:阮一峰的博客</a></p>
<h4><strong>2. 本地存储</strong></h4>
<p>在html5之前,本地存储只有cookie(flash cookie)这么一种选择,但是cookie的容量很小,并且安全性上得不到保障。<br>在html5中,新增了两种存储方式:<code>local storage</code>和<code>session storage</code>,local storage是永久性的存储,大小大概是5MB, session storage时临时的,浏览器关闭即刻清空。其实这两个东西是一个东西,放在内存中是session storage,在文件系统中是local storage。</p>
<p><a href="https://link.segmentfault.com/?enc=KImlsItMUl9jWtFjFzonGA%3D%3D.8CJruF%2B6ECc3pUo2%2F1i5D3ZJvrvr8JiEJMCobwKPNttBj%2FNH3lEaUugdXLllpidCUfIfcwMHaT2SzpGwCcud4A%3D%3D" rel="nofollow">具体使用方法请见:w3school.com.cn</a></p>
<h4><strong>3. web sql(本地数据库 已废弃)</strong></h4>
<p>同时,html5提供了本地数据库支持,默认是sqlite这一轻量级的数据库,可以存储一些临时资料或者缓存。</p>
<p><a href="https://link.segmentfault.com/?enc=FJd6r9mChFkA2Ege2pflGA%3D%3D.c%2BWQICDX8ymv36Xoz7lbE%2FCgWZMptnVYItZktNRWvwmKZ8LSgxCiVwR1pDskyOTJX47k5Paozyliuw3g%2BxEeTg%3D%3D" rel="nofollow">操作方式详见此处</a></p>
<h4><strong>4. web worker(js多线程执行)</strong></h4>
<p>由于js时单线程执行的,所以在h5之前,执行js是会阻塞UI的,h5实现了web worker这一机制,从而使得js也可以使用子线程去执行任务从而不阻塞主UI线程了。</p>
<p><a href="https://link.segmentfault.com/?enc=g7a6b%2FuFZ%2BQgwalBUsR8tQ%3D%3D.Vg3dAWV6Bt6q8EctWjvkAhbEECo0OjWJ1sR44HjjvAdrDfs2LqBdFvRxhhxWg3tCxV9icFUzj6SRMCwZ%2F%2BWW%2FA%3D%3D" rel="nofollow">操作方式详见此处</a></p>
<h4><strong>5. web socket (服务器推送机制)</strong></h4>
<p>由于http时无状态单连接的协议,所以在过去,只能是客户端发送request,服务器响应response,现在h5实现了websocket这一机制,从而可以保持长链接,服务器可以主动推送信息到客户端了。当然需要服务器支持websocket机制。<br><a href="https://link.segmentfault.com/?enc=w2C6NHEOih1KEW9WEv3abg%3D%3D.r0cqK6mkEGeZqADCKrsUIJOopgcO8qEWa4Wm7EC4YMzEUTULwNyn1FGSF96D7iNFcHs2KGxICvml2e79wcOqODbWKNsNKHXgKAwlSVY5hfWO97%2Fgsxv%2Fg6WY7ICk7SzbIBldv0MA8deU%2F6zQkncYtA%3D%3D" rel="nofollow">具体使用方式</a></p>
<h4><strong>6. 新标签和新api</strong></h4>
<p>h5新实现了一些比较便捷的标签和api,使得用户对第三方插件的依赖能过有所减少,从而减少不可控安全问题。<br>比如<code><video></code>,<code><audio></code>,<code><canvas></code>等等。<br>同时实现了比较多的新的api,比如地理位置api,putstate等等。<br><a href="https://link.segmentfault.com/?enc=KsTys9RaFwue%2Bicqgb1qRQ%3D%3D.n%2ByvnpaYpCRA1NW7VUOIPCtGj8L5OX1bxhA2epQtIZY8hmbwFboMr7w04q4xjCT7" rel="nofollow">具体请查看:w3school.com.cn</a></p>
<hr>
<h3>0x02 Ajax跨域资源共享(CORS)安全问题</h3>
<h4>1. 跨域资源请求的方式:</h4>
<ul>
<li><p>ajax在之前是要严格遵守同源策略的,但是在h5中为了提供更好的使用性,诞生了ajax跨域的方式-CORS。跨域资源共享是为了解决跨域请求的问题的。</p></li>
<li><p>除了CORS这个方案,还有另外两种跨域请求的方法,一个是使用jsonp的方式,一个是使用flash的跨域方案,通过服务器上的crossdomain.xml来控制跨域。</p></li>
</ul>
<h4>2. CORS的做法:</h4>
<p>CORS的跨域方式是通过:Access–Control-Allow-Origin这个头以及其他的头来实现的,客户端跨域访问一个服务器,服务器会确定这个这个域名是否有权限来获取资源,若有则返回一个带有Access–Control-Allow-Origin头的response以及资源。若无则返回一个权限错误:XMLHttpRequest cant load .....</p>
<h4>3. 风险点:</h4>
<p>(1). 对Access–Control-Allow-Origin设置为*,并且没有携带会话认证,这样子意味着信息被公开在全网。<br>(2). http头可以伪造。http可以伪造意味着http头中的域名(origin)可以是假的,所以跨域是要配合身份验证进行的,所以跨域的时候记得带上session id。<br>(3). 就算是使用了session id,但是第三方有可能也会被入侵,从而导致源站信息泄露,所以CORS是一个非常危险的东西。<br>(4). 内部信息泄露,内部成员打开一个evil website,导致个人会话信息泄露,那么内部网站的数据将会泄露<br>(5). 另外,不是设置了Access–Control-Allow-Origin,并且对请求站点做了权限控制,就可以防止信息泄露,在返回权限错误的时候,请求的信息其实已经到了客户端。<br>(6). CORS默认不能携带会话信息,但是如果将withCredentials设置为true,则可以携带,所以这个属性最好设置为false。万一需要设置为true,请在Access–Control-Allow-Origin上设置具体的域名,不要使用 *。这是CORS的最后一层遮羞裤了,设置不好就裸奔了。</p>
<h4>4. 防御姿势:</h4>
<ul>
<li><p>不要对Access–Control-Allow-Origin使用 *</p></li>
<li><p>要对跨域请求验证session信息。</p></li>
<li><p>严格审查请求信息,比如请求参数,还有http头信息。</p></li>
</ul>
<h4>5. 利用姿势:</h4>
<p>CORS主要是提供了一种隐形的跨域数据传输方式,偷取信息用户是不能感受到的,主要是两种利用方式。</p>
<ol>
<li><p>第一个是需要将跨域js植入到被攻击的页面,这样子可以劫持到对方的cookie等认证信息。这种方式就是通过一个xss或者sqli,将js植入目标服务器,这样子就可以将认证信息偷过来了,如果是存储型就就更赞了,可以实时更新认证信息。</p></li>
<li><p>第二个是将跨域放在自己控制的网站上,通过用户点击来攻击指定由CORS漏洞的服务器。这个要求目标服务器对CORS没有设置好,有CORS配置漏洞。</p></li>
<li><p>另外ajax跨域不存在问题了,那么是不是CSRF也可以更隐蔽的进行了呢</p></li>
</ol>
<h4>6. 参考:</h4>
<p><a href="https://link.segmentfault.com/?enc=BAVHl325YCRXpnydmaDeiA%3D%3D.0ws5Uv9kCaOHp0%2FGhrHwCzh3c4BKpDtd6YqLCHRgj9kcMCp1da3w%2FcJwokU3lsSWW81G6oSot02JdHEV9lZkMA%3D%3D" rel="nofollow">51CTO h5安全专题</a><br><a href="https://link.segmentfault.com/?enc=TPeEA8vSaq2%2B0qo12O7njw%3D%3D.VM5OXM86hxLd71gzx3hxG4W5TXCAp8zf9J%2BmNZ79XfGKcpdNFFvebVYnhAx%2FIS3FNHugV6ZBTxk3%2FFcu2IB0Lg%3D%3D" rel="nofollow">51CTO 文章</a></p>
<h3>0x03 本地存储安全问题</h3>
<p>这里的本地存储主要指的是localstorage和sessionstorage。其他的比如windows.history,png cache等等不做讨论。</p>
<p>就如余弦说的,localstorage是大势所趋,因为随着网站的复杂性升级,cookie最多只能有4k,每个网站只能存放30或者50个cookie,这样大大制约了web的发展。所以localstorage和sessionstorage出现了(后面将不分开讨论)。</p>
<h4>使用方式:</h4>
<p>localstorage使用只能通过js去进行写入或者读取,存放格式为key-value格式,比如<code>localStorage.set("key","value")</code>.这个意味着他没有cookie那么安全。</p>
<h4>风险点:</h4>
<ol>
<li><p>js获取,因为是只能通过js设置和获取,导致的结果是不能像cookie一样设置httponly。所以可以配合CORS来获取网站的localstorage的信息。所以localstorage中不能存放敏感信息。</p></li>
<li><p>因为在各大主流的浏览器中,除了opera采用base64加密,其他都是采用明文存储的,所以在存储的时候最好在服务器端进行加密。</p></li>
<li><p>还有一个,可能会被植入广告追踪标志。</p></li>
</ol>
<h4>防御姿势:</h4>
<ol>
<li><p>不要存放敏感信息。</p></li>
<li><p>选择合适的域存放合适的信息,比如一次过期的信息就放在sessionstorage中。</p></li>
<li><p>对存放在其中的信息最好能够在服务端进行加密。</p></li>
</ol>
<h4>利用姿势:</h4>
<ol><li><p>配合CORS或者XSS获取本地存储中的数据。</p></li></ol>
<h3>0x04 本地SQL安全问题</h3>
<p>H5在之前引入了本地SQL这个东西,但是后面被废除了,他的安全点和后台数据库的关注点差不多,就是要防止在数据中混入sql查询指令。这里不再展开。</p>
<h3>0x05 Web worker僵尸网络风险</h3>
<p>H5中“解决”了js单线程问题,提出了web worker机制,它为js提供多线程支持,但是多线程带来了一个非常可怕的危险-僵尸网络。</p>
<h4>使用方式:</h4>
<pre><code>var worker = new Worker("worker.js");
worker.postMessage("hello world");
worker.onmessage = function(){}</code></pre>
<h4>风险点:</h4>
<p>风险点只有一个,那就是在用户不知情的情况下,使用pc端的资源往外发送大量的请求,如果受控的客户端(僵尸)够多,并且针对某一个目标发送,可以造成应用层的DDOS。(虽然是异域,但是不需要CORS配合,因为CORS只是限制客户端是否能够拿到服务器的数据,而不会限制发送这个事情)<br>其实这里还有一个<code>postMessage</code>的问题,放到API风险那个小结。</p>
<h4>防御姿势:</h4>
<ol>
<li><p>不要访问不安全的站点</p></li>
<li><p>用户注意观察客户端资源占用情况,发现某个页面资源占用反常就关掉。</p></li>
</ol>
<h4>利用方式:</h4>
<p>非常清晰,写一个webworker,然后注入到一些页面中去,只要访问这个页面,web worker就开始工作。</p>
<h3>0x06 Web socket 嗅探内部端口</h3>
<p>H5的web socket 颠覆了传统的http通信方式(request-response),他通过建立一个长链接,让服务器可以随时推送消息给客户端,而不是采用轮询的方式去做这个事情。</p>
<h4>风险点</h4>
<p>他是通过开启另外一个非80的端口去做这件事情。从而导致嗅探的可能性。</p>
<h3>0x06 新标签带来的XSS风险</h3>
<p>H5引进了很多新的标签,比如<code><video><audio><cavans></code>等等,具体的可以去<a href="https://link.segmentfault.com/?enc=R1WvaTcpomlp0LkdqhZsZA%3D%3D.opxdmq9DIiJaGd0lJdHtmj6n%2FrvUFaWXdjaRqYsVCOD4wj0jpv%2FbR9B1P5WHY8%2Ba" rel="nofollow">w3school</a>查看。<br>新标签意味着之前指定的xss过滤或者转义规则可能会不适用。</p>
<h4>1. 新标签</h4>
<p>新的方式如下:</p>
<pre><code><video onerror=alert(1)><source>
<video><sourceonerror="javascript:alert(1)"
<video src=".." onloadedmetadata="alert(1)" ondurationchanged="alert(2)" ontimeupdate="alert(3)"></video>
<video><sourceonerrorsourceonerrorsourceonerrorsourceonerror="javascript:alert(1)“>
<videopostervideopostervideopostervideoposter=”javascript:alert(1)”> </code></pre>
<p>待补充#todo</p>
<h4>2. 新属性</h4>
<p>新方式如下:</p>
<pre><code><form id="test" /><button form="test" formaction="javascript:alert(1)">X
<form id=test onforminput=alert(1)><input></form><button form=test on formchange=alert(2)>X
<input onfocus=write(1) autofocus></code></pre>
<p>待补充#todo<br>更多可查看:<a href="https://link.segmentfault.com/?enc=8LvS03vxn0Yrx2ECO%2F%2BYXA%3D%3D.BTNYbmYzL%2BiQHzqU68fifOGV7M19chjGLChSm7QMZUw%3D" rel="nofollow">HTML5 标签安全</a></p>
<h3>0x07 新API安全</h3>
<h4>1. postMessage</h4>
<p>postMessage是web worker中的一个函数,它的作用是主线程给新线程post数据用的,但是有一个问题就是postMessage是不通过服务器的,那么很有可能造成DOM-based XSS。</p>
<p><strong>防御方式</strong><br>但是postMessage的防御点不在本身,而在onmessage上,onmessage中不能直接使用innerHTML类似的语句添加或者修改网页。</p>
<p><strong>利用方式:</strong></p>
<pre><code>postMessage("<script>alert(1)</script>");
worker.onmessage = function(e) {
document.getElementById("test").innerHTML = e.data;
}</code></pre>
<h4>2. History API</h4>
<p>H5在History API新增了两个API:pushState()和replaceState(),这两个方法可以在不刷新页面的情况下添加或者修改历史条目</p>
<ul>
<li><p>pushState(data,title [, url])<br>他的作用是在浏览器历史列表的站定添加一条记录,一个是状态,一个是标题,一个是URL(可选,同域)</p></li>
<li><p>replaceState(data,tile [,url])<br>参数和上一个相同,它的作用是更改当前页面的历史纪录。</p></li>
</ul>
<p><strong>利用方式:</strong><br>可以利用他来伪装GET方法下的反射型xss。<br>比如,存在一个有漏洞的链接 <code>http://www.foo.com/?a=1</code>,可以进行XSS注入,如:<code>http://www.foo.com/?a=<script>alert(1)</script></code></p>
<p>但是如果这么直接写在页面上让用户点击,一般都会发现有问题,所以可以采用短链接的方式,假设上述链接转换为:<code>http://www.foo.com/TqsjW</code>,用户应该会点过去了,但是点过去之后,URL栏中还是原来的长链接,同样会被发现。</p>
<p>但是这么写的话:</p>
<pre><code>http://www.foo.com/?a=<script>history.pushState({},'',location.href.split("?").shift();alert(1))</script></code></pre>
<p>将他转换成短链接,点击之后,会转换到<code>http://www.foo.com/</code>这个上面,所以就完美的隐藏了。</p>
Python类继承的高级特性
https://segmentfault.com/a/1190000000749061
2014-10-30T14:03:49+08:00
2014-10-30T14:03:49+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
4
<h4>昨天在Python类的多重继承那里纠结了好久,在提问版块提了个问题探讨了探讨(<a rel="nofollow" href="http://segmentfault.com/q/1010000000747840">链接</a>)才完全搞明白,现在把类的特性整理下,供以后参考</h4>
<h2>正文</h2>
<p>首先得说明的是,Python的类分为<strong>经典类</strong> 和 <strong>新式类</strong><br>
经典类是python2.2之前的东西,但是在2.7还在兼容,但是在3之后的版本就只承认新式类了<br>
新式类在python2.2之后的版本中都可以使用</p>
<h4>经典类和新式类的区别在于:</h4>
<ol>
<li>经典类是默认没有派生自某个基类的,而新式类是默认派生自<code>object</code>这个基类的:</li>
</ol>
<pre><code># old style
class A():pass
# new style
class A(obejct):pass
</code></pre>
<p>2.经典类在类多重继承的时候是采用<code>从左到右深度优先</code>原则匹配方法的..而新式类是采用<code>C3算法</code>(不同于广度优先)进行匹配的</p>
<p>3.经典类是没有<code>__MRO__</code>和<code>instance.mro()</code>调用的,而新式类是有的.</p>
<h4>为什么不用经典类,要更换到新式类</h4>
<p>因为在经典类中的多重继承会有些问题...可能导致在继承树中的方法查询绕过后面的父类:</p>
<pre><code>class A():
def foo1(self):
print "A"
class B(A):
def foo2(self):
pass
class C(A):
def foo1(self):
print "C"
class D(B, C):
pass
d = D()
d.foo1()
</code></pre>
<p>按照经典类的查找顺序<code>从左到右深度优先</code>的规则,在访问<code>d.foo1()</code>的时候,D这个类是没有的..那么往上查找,先找到B,里面没有,深度优先,访问A,找到了foo1(),所以这时候调用的是A的foo1(),从而导致C重写的foo1()被绕过.</p>
<p>所以python引入了新式类的概念,每个基类都继承自<code>object</code>并且,他的匹配规则也从<code>深度优先</code>换到了<code>C3</code></p>
<hr>
<h4>C3算法</h4>
<p>C3算法是怎么做匹配的呢..在问答版块上面讨论之后,归结如下:</p>
<p>C3算法的一个核心是<code>merge</code>.</p>
<blockquote>
<p>在merge列表中,如果第一个序列mro的第一个类是出现在其它序列,并且也是第一个,或者不出现其它序列,那么这个类就会从这些序列中删除,并合到访问顺序列表中</p>
</blockquote>
<p>比如:(引用问题中<a rel="nofollow" href="http://segmentfault.com/u/zhuangzebo">zhuangzebo</a>的回答@zhuangzebo)</p>
<pre><code>class A(O):pass
class B(O):pass
class C(O):pass
class D(A,B):pass
class E(C,D):pass
</code></pre>
<p>首先需要知道 O(object)的<code>mro</code>(method resolution order)列表是[O,]<br>
那么接下来是:</p>
<pre><code>mro(A) = [A, O]
mro(B) = [B, O]
mro(C) = [C, O]
mro(D) = [D] + merge(mro(A), mro(B), [A, B])
= [D] + merge([A, O], [B, O], [A, B])
= [D, A] + merge([O], [B, O], [B])
= [D, A, B] + merge([O], [O])
= [D, A, B, O]
mro(E) = [E] + merge(mro(C), mro(D), [C, D])
= [E] + merge([C, O], [D, A, B, O], [C, D])
= [E, C] + merge([O], [D, A, B, O], [D])
= [E, C, D] + merge([O], [A, B, O])
= [E, C, D, A, B] + merge([O], [O])
= [E, C, D, A, B, O]
</code></pre>
<p><strong>然后还有一种特殊情况:</strong><br>
比如:<br><code>merge(DO,CO,C)</code> 先merge的是D<br><code>merge(DO,CO,C)</code> 先merge的是C<br>
意思就是.当出现有 <code>一个类出现在两个序列的头(比如C)</code> 这种情况和 <code>这个类只有在一个序列的头(比如D)</code> 这种情况同时出现的时候,按照顺序方式匹配。</p>
<p>新式类生成的访问序列被存储在一个叫<strong>MRO</strong>的只读列表中..<br>
你可以使用<code>instance.__MRO__</code>或者<code>instance.mro()</code>来访问</p>
<p>最后匹配的时候就<strong>按照<strong>MRO</strong>序列的顺序去匹配</strong>了</p>
<h4>C3和广度优先的区别:</h4>
<p>举个例子就完全明白了:</p>
<pre><code>class A(object):pass
class B(A):pass
class C(B):pass
class D(A):pass
class E(D):pass
class F(C, E):pass
</code></pre>
<p>按照广度优先遍历,F的MRO序列应该是<code>[F,C,E,B,D,A]</code><br>
但是C3是<code>[F,E,D,C,B,A]</code><br>
意思是你可以当做C3是在一条链路上深度遍历到和另外一条链路的交叉点,然后去深度遍历另外一条链路,最后遍历交叉点</p>
<h4>新式类和经典类的<code>super</code>和<code>按类名访问</code>问题</h4>
<p>在经典类中,你如果要访问父类的话,是用类名来访问的..</p>
<pre><code>class A():
def __init__(self):
print "A"
class B(A):
def __init__(self):
print "B"
A.__init__(self) #python不会默认调用父类的初始化函数的
</code></pre>
<p>这样子看起来没三问题,但是如果类的继承结构比较复杂,会导致代码的<code>可维护性很差</code>..<br>
所以新式类推出了<code>super</code>这个东西...</p>
<pre><code>class A():
def __init__(self):
print "A"
class B(A):
def __init__(self):
print "B"
super(B,self).__init__()
</code></pre>
<p>这时候,又有一个问题:<strong>当类是多重继承的时候,super访问的是哪一个类呢?</strong><br>
super实际上是通过<code>__MRO__</code>序列来确定访问哪一个类的...实际上就是调用<code>__MRO__</code>中此类后面的一个类的方法.<br>
比如序列为<code>[F,E,D,C,B,A]</code>那么F中的super就是E,E的就是D</p>
<h4>
<code>super</code>和<code>按照类名访问</code> 混合使用带来的坑</h4>
<pre><code>class A(object):
def __init__(self):
print "enter A"
print "leave A"
class B(object):
def __init__(self):
print "enter B"
print "leave B"
class C(A):
def __init__(self):
print "enter C"
super(C, self).__init__()
print "leave C"
class D(A):
def __init__(self):
print "enter D"
super(D, self).__init__()
print "leave D"
class E(B, C):
def __init__(self):
print "enter E"
B.__init__(self)
C.__init__(self)
print "leave E"
class F(E, D):
def __init__(self):
print "enter F"
E.__init__(self)
D.__init__(self)
print "leave F"
</code></pre>
<p>这时候打印出来是:</p>
<pre><code> enter F
enter E
enter B
leave B
enter C
enter D
enter A
leave A
leave D
leave C
leave E
enter D
enter A
leave A
leave D
leave F
</code></pre>
<p>可以看出来D和A的初始化函数被乱入了两次!<br><code>按类名访问</code>就相当于C语言之前的<code>GOTO</code>语句...乱跳,然后再用<code>super</code>按顺序访问..就有问题了</p>
<p>所以建议就是要么一直用<code>super</code>,要么一直用<code>按照类名访问</code></p>
<h4>最佳实现:</h4>
<ol>
<li>避免多重继承</li>
<li>super使用一致</li>
<li>不要混用经典类和新式类</li>
<li>调用父类的时候注意检查类层次</li>
</ol>
<h4>参考资料:</h4>
<ol>
<li>《python高级编程》</li>
<li><a rel="nofollow" href="http://www.cnblogs.com/lovemo1314/archive/2011/05/03/2035005.html">http://www.cnblogs.com/lovemo1314/archive/2011/05/03/2035005.html</a></li>
<li><a rel="nofollow" href="http://www.cnblogs.com/i2u9/archive/2013/03/19/pythonmroc3.html">http://www.cnblogs.com/i2u9/archive/2013/03/19/pythonmroc3.html</a></li>
</ol>
ECS+nginx+wordpress一手搭建完毕
https://segmentfault.com/a/1190000000743190
2014-10-27T17:37:42+08:00
2014-10-27T17:37:42+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
1
<h3>PS:</h3>
<p><strong>先来一段吐槽...好朋友校招进百度前端团队了..我还在找工作ing..好心塞.但是蛮为他高兴的.</strong></p>
<p><strong>是我的问题.技术面铺的太开了,没有深入的一项.比较深入的也就是web渗透,python了吧.但是渗透团队要求好高!网易跪在了HR面..绿盟进行中(工资略低啊)</strong></p>
<p><strong>技能点大概是(10星满分):python(7星),linux(6星),web渗透(6星),html+js(4星),网络安全(7星),学习能力(10星,哇咔咔),</strong><br><strong>今后就三个方向:渗透,python,linux不变了!吃够了不专注的苦了!</strong></p>
<h3>但是事情还得做!明天更美好!</h3>
<hr>
<p>这篇文章主要为了记录一些配置过程中的问题,但是我不喜欢写半拉子东西,所以就完整记录下吧,我会分好几个时间段来写的...</p>
<h2>#正文#</h2>
<p>穷人终于有了一个云主机(和别人合买的!哭)<br>
那么昨晚就开开心心的把环境配了配.<br>
环境:<br>
ubuntu 12.04</p>
<h2>step 1:安装和配置必要软件</h2>
<p>首先你得ssh到云主机上面<br>
假设你的云主机独立IP为<code>x.x.x.x</code></p>
<h3>nginx</h3>
<p>nginx 是另外一个哥们手动编译过来的,我这里就不介绍怎么编译了..</p>
<p><strong>安装命令</strong>:<code>sudo apt-get install nginx</code></p>
<p><strong>启动</strong>:<code>sudo nginx</code><br>
可选参数<code>-c</code>.指定配置文件的路径..用默认的就ok啦..</p>
<p><strong>停止</strong>:<code>sudo nginx -s stop</code></p>
<p><strong>每次改变配置文件之后要reload才能生效</strong>:<code>sudo nginx -s reload</code></p>
<p><strong>配置文件解析:</strong><br>
nginx有个默认配置文件:<br>
默认的是:<code>/etc/nginx/ngnix.conf</code>和<code>/etc/nginx/site-available/default</code>.</p>
<hr>
<p>打开配置文件:<br><code>sudo vim /etc/nginx/ngnix.conf</code><br><code>sudo vim /etc/nginx/site-available/default</code></p>
<hr>
<p>其中 <code>ngnix.conf</code>是总配置文件,里面有<code>http</code> block,<code>events</code> block,<code>mail</code>block(略过)</p>
<p><code>ngnix.conf</code>中从头开始讲:</p>
<ol>
<li><p><code>user www-data</code>在你安装ngnix的时候已经建立了这个用户,不用管他</p></li>
<li><p><code>worker_processes 1;</code> 这里数值最大为4,表明开几个线程处理请求.</p></li>
<li><p><code>http {}</code>主要配置一些公用属性:日志存放地点,配置文件包含,服务器是否接受gzip.保持连接时间,接受文件类型等等..但是刚刚搭建的话就采用默认就好了,具体如下:</p></li>
</ol>
<pre><code>http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
types_hash_max_size 2048;
proxy_ignore_client_abort on;
#keepalive_timeout 0;
keepalive_timeout 65;
gzip on;
gzip_disable "msie6";
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
server {}
}
</code></pre>
<p>4.和http并行的有一个<code>events{}</code>block,里面一边配置的只有一条属性:</p>
<pre><code>events {
worker_connections 1024;
}
</code></pre>
<p>就是最大连接数</p>
<p>5.最后会发现有这么几行配置:</p>
<pre><code> include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
</code></pre>
<p>表明include了其他的配置文件,如果按照路径去查找,最终会发现只include进来一个<code>/etc/nginx/site-available/default</code>文件</p>
<hr>
<p><code>default</code>里面的内容,其他什么都不要管,关键是这几个block:<br>
1. <code>sever{}</code> 这个相当于apache的虚拟目录...你可以配置多个server.让他监听不同的端口,或者分发不同的域名.<br>
2. <code>location{}</code> 这个是做路径路由的..就是匹配你request里面的路径的.(他是嵌套在server里面的)</p>
<hr>
<p>先从<code>server{}</code>讲起.里面的关键语句有:<br><code>listen port</code>: port一般默认都是<code>80</code>因为是http嘛<br><code>root path</code>:<code>path</code>是你的网站根目录,相当于apachce的<code>www-root</code><br><code>server_name your_domain_name</code>:后面是你的域名,默认是localhost用来本机测试.可以用这边做站点分发哦..</p>
<hr>
<p>然后是 <code>location{}</code><br>
他是<code>server</code>里面的子嵌套..一个server里面可以有多个来匹配不同的路径..</p>
<p>1.首先必须配的是 <code>location /{}</code><br>
这个用来匹配所有请求的,每个请求都会进入这个location来,然后nginx来去看路径是否有这个文件..若有的话,静态文件直接返回,动态脚本交给下面的location处理.<br>
格式化配置内容如下:</p>
<pre><code>location / {
try_files $uri $uri/ =404;
autoindex on;
index index.php index.html index.htm;
}
</code></pre>
<p><code>index</code>是为了找出默认首页..顺序匹配</p>
<p>2.如果是php动态脚本的话..需要如下location</p>
<pre><code>location ~ \.php$ {
# fastcgi_pass unix:/var/run/php5-fpm.sock;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
</code></pre>
<p>3.如果是python脚本的话,如下:</p>
<pre><code> location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:50000;
}
</code></pre>
<p>这里很容易出问题的..用unix sock的话我是没试过..</p>
<p>检测nginx是否正常工作:<br>
在浏览器中输入:<a rel="nofollow" href="http://x.x.x.x/">http://x.x.x.x/</a>跳出<code>welcome to use nginx</code>即可</p>
<hr>
<h3>php相关组件</h3>
<p>安装过程:<br><code>sudo apt-get install php5 php5-cgi php5-fpm php5-mysql</code></p>
<p>php5-fpm的配置文件无需修改,有兴趣的可以去<code>/etc/php5/fpm/php-fpm.conf</code>和<code>/etc/php5/fpm/php.ini</code>查看</p>
<p>检测php5-fpm服务是否开启:<br><code>sudo netstat -tunpl | grep 9000</code></p>
<p>开启关闭重启php5-fpm方法:<br><code>sudo service php5-fpm start</code><br><code>sudo service php5-fpm stop</code><br><code>sudo service php5-fpm restart</code></p>
<hr>
<h3>现在可以检测下php和nginx是否配置好了:</h3>
<ol>
<li>在你ngnix配置的root属性指向的目录下存放一个文件叫<code>index.php</code>
</li>
<li>在你nginx配置中 index配置下将<code>index.php</code>放在首位</li>
<li>在index.php中写入:</li>
</ol>
<pre><code><?php
phpinfo();
?>
</code></pre>
<p>最后访问<a rel="nofollow" href="http://x.x.x.x">http://x.x.x.x</a> 若有php配置信息跳出即成功</p>
<hr>
<h3>mysql</h3>
<p>安装方法:<br><code>sudo apt-get install mysql-server mysql-client</code></p>
<p>安装过程中会让你输入mysql的root用户的新密码,按照步骤执行即可</p>
<hr>
<h3>安装wordpress</h3>
<p>1.从官网下载wordpress4.0<br><code>wget https://cn.wordpress.org/wordpress-4.0-zh_CN.zip</code></p>
<p>2.解压缩:<br><code>unzip wordpress-4.0-zh_CN.zip</code></p>
<p>3.将解压的文件放到你的web目录下(可能需要修改配置文件将root指向wordpress文件夹)</p>
<p>4.修改源码(因为wordpress使用了google字体,而google字体在线加载特别缓慢,影响速度)<br>
找到<code>wordpress/wp-includes/script-loader.php</code><br>
打开该文件,查找<code>fonts.google.com</code>然后将这个链接改为<code>fonts.useso.com</code>即可</p>
<p>5.在浏览器中输入http:/x.x.x.x即可进入安装页面,按照步骤操作即可</p>
<h2>step 2:域名绑定</h2>
<p>阿里云主机是有独立IP的,假设为<code>x.x.x.x</code><br>
如果你有个域名,但是不是在阿里云或者万网做的备案,那么就麻烦了(我就是这样子!)<br>
你需要按照阿里云的转入备案流程将你的备案转入过来,否则你的域名指向该IP的时候阿里云会检测到然后不让你访问,如下图:<br><img src="/img/bVdikA" alt="图片描述"></p>
<p>所以你得先去做转入备案...具体流程请看:<a rel="nofollow" href="http://beian.aliyun.com/not-at-aliyun.html?spm=5176.200001.5.3.qB7fXw">http://beian.aliyun.com/not-at-aliyun.html?spm=5176.200001.5.3.qB7fXw</a></p>
<p>做完备案转入之后按照常规的,将域名使用A解析指向你的IP地址即可</p>
<h3>step3:wordpress主题插件更新</h3>
<p>wordpress更新插件有两种方式:<br>
1. 在线更新:是要用FTP上传的,所以你需要搭建一个FTP服务器在你的云主机上,具体教程请查看:<br><a rel="nofollow" href="http://blog.csdn.net/njchenyi/article/details/8499555">http://blog.csdn.net/njchenyi/article/details/8499555</a><br>
2. 离线形式,你先将插件包或者主题包下载下来,然后手动传到指定目录即可.<br>
主题目录为:<code>wordpress/wp-content/themes/</code><br>
插件目录为:<code>wordpress/wp-content/plugins/</code></p>
<h2>安装过程中问题荟萃</h2>
<ol>
<li><p>测试php环境是否安装成功的时候,返回200状态码,但是页面是白板.<br>
解决方法:<br>
查看error.log(<code>sudo vim /var/log/nginx/error.log</code>)你会发现有个文件夹<code>permission denied</code><br>
所以去把那个文件夹(<code>/usr/local/nginx/fastcgi_temp</code>)给<code>sudo chmod 777 fastcgi_temp</code>即可</p></li>
<li><p>若出现访问页面返回一大堆js代码的情况:<br>
在nginx.conf中删除除了以上说到的关于fastcgi和fpm的配置</p></li>
</ol>
linux下使用openssl对socket通信加密
https://segmentfault.com/a/1190000000736700
2014-10-23T14:15:26+08:00
2014-10-23T14:15:26+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
2
<h2>普通socket编程</h2>
<p>TCP服务器端</p>
<pre><code>#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int server_sockfd;//服务器端套接字
int client_sockfd;//客户端套接字
int len;
struct sockaddr_in my_addr; //服务器网络地址结构体
struct sockaddr_in remote_addr; //客户端网络地址结构体
int sin_size;
char buf[BUFSIZ]; //数据传送的缓冲区
memset(&my_addr,0,sizeof(my_addr)); //数据初始化--清零
my_addr.sin_family=AF_INET; //设置为IP通信
my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上
my_addr.sin_port=htons(8000); //服务器端口号
/*创建服务器端套接字--IPv4协议,面向连接通信,TCP协议*/
if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)
{
perror("socket");
return 1;
}
/*将套接字绑定到服务器的网络地址上*/
if (bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)
{
perror("bind");
return 1;
}
/*监听连接请求--监听队列长度为5*/
listen(server_sockfd,5);
sin_size=sizeof(struct sockaddr_in);
/*等待客户端连接请求到达*/
if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&remote_addr,&sin_size))<0)
{
perror("accept");
return 1;
}
printf("accept client %s/n",inet_ntoa(remote_addr.sin_addr));
len=send(client_sockfd,"Welcome to my server/n",21,0);//发送欢迎信息
/*接收客户端的数据并将其发送给客户端--recv返回接收到的字节数,send返回发送的字节数*/
while((len=recv(client_sockfd,buf,BUFSIZ,0))>0))
{
buf[len]='/0';
printf("%s/n",buf);
if(send(client_sockfd,buf,len,0)<0)
{
perror("write");
return 1;
}
}
close(client_sockfd);
close(server_sockfd);
return 0;
}
</code></pre>
<p>TCP客户端编程(socket_comunication_client.c)</p>
<pre><code>#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int client_sockfd;
int len;
struct sockaddr_in remote_addr; //服务器端网络地址结构体
char buf[BUFSIZ]; //数据传送的缓冲区
memset(&remote_addr,0,sizeof(remote_addr)); //数据初始化--清零
remote_addr.sin_family=AF_INET; //设置为IP通信
remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器IP地址
remote_addr.sin_port=htons(8000); //服务器端口号
/*创建客户端套接字--IPv4协议,面向连接通信,TCP协议*/
if((client_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)
{
perror("socket");
return 1;
}
/*将套接字绑定到服务器的网络地址上*/
if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0)
{
perror("connect");
return 1;
}
printf("connected to server/n");
len=recv(client_sockfd,buf,BUFSIZ,0);//接收服务器端信息
buf[len]='/0';
printf("%s",buf); //打印服务器端信息
/*循环的发送接收信息并打印接收信息--recv返回接收到的字节数,send返回发送的字节数*/
while(1)
{
printf("Enter string to send:");
scanf("%s",buf);
if(!strcmp(buf,"quit")
break;
len=send(client_sockfd,buf,strlen(buf),0);
len=recv(client_sockfd,buf,BUFSIZ,0);
buf[len]='/0';
printf("received:%s/n",buf);
}
close(client_sockfd);//关闭套接字
return 0;
}
</code></pre>
<p>以上代码转载自<a rel="nofollow" href="http://blog.csdn.net/piaojun_pj/article/details/5920888">linux socket编程</a></p>
<h2>Openssl AES加密</h2>
<ol>
<li>
<strong>首先安装openssl和相关库(Ubuntu)</strong><br><code>apt-get install openssl libssl-dev</code>
</li>
<li><strong>编写相关加密解密代码</strong></li>
</ol>
<ul>
<li>aes_options.h</li>
</ul>
<pre><code>#ifndef _ASE_H_
#define _ASE_H_
int encrypt(char *input_string, char **encrypt_string);
void decrypt(char *encrypt_string, char **decrypt_string, int len);
#endif
</code></pre>
<ul>
<li>aes_options.c</li>
</ul>
<pre><code>#include <stdio.h>
#include <openssl/aes.h>
#include <stdlib.h>
#include <string.h>
int encrypt(char *input_string, char **encrypt_string)
{
AES_KEY aes;
unsigned char key[AES_BLOCK_SIZE]; // AES_BLOCK_SIZE = 16
unsigned char iv[AES_BLOCK_SIZE]; // init vector
unsigned int len; // encrypt length (in multiple of AES_BLOCK_SIZE)
unsigned int i;
// set the encryption length
len = 0;
if ((strlen(input_string) + 1) % AES_BLOCK_SIZE == 0)
{
len = strlen(input_string) + 1;
}
else
{
len = ((strlen(input_string) + 1) / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
}
// Generate AES 128-bit key
for (i=0; i<16; ++i) {
key[i] = 32 + i;
}
// Set encryption key
for (i=0; i<AES_BLOCK_SIZE; ++i) {
iv[i] = 0;
}
if (AES_set_encrypt_key(key, 128, &aes) < 0) {
fprintf(stderr, "Unable to set encryption key in AES\n");
exit(0);
}
// alloc encrypt_string
*encrypt_string = (unsigned char*)calloc(len, sizeof(unsigned char));
if (*encrypt_string == NULL) {
fprintf(stderr, "Unable to allocate memory for encrypt_string\n");
exit(-1);
}
// encrypt (iv will change)
AES_cbc_encrypt(input_string, *encrypt_string, len, &aes, iv, AES_ENCRYPT);
return len;
}
void decrypt(char *encrypt_string, char **decrypt_string,int len)
{
unsigned char key[AES_BLOCK_SIZE]; // AES_BLOCK_SIZE = 16
unsigned char iv[AES_BLOCK_SIZE]; // init vector
AES_KEY aes;
int i;
// Generate AES 128-bit key
for (i=0; i<16; ++i) {
key[i] = 32 + i;
}
// alloc decrypt_string
*decrypt_string = (unsigned char*)calloc(len, sizeof(unsigned char));
if (*decrypt_string == NULL) {
fprintf(stderr, "Unable to allocate memory for decrypt_string\n");
exit(-1);
}
// Set decryption key
for (i=0; i<AES_BLOCK_SIZE; ++i) {
iv[i] = 0;
}
if (AES_set_decrypt_key(key, 128, &aes) < 0) {
fprintf(stderr, "Unable to set decryption key in AES\n");
exit(-1);
}
// decrypt
AES_cbc_encrypt(encrypt_string, *decrypt_string, len, &aes, iv,
AES_DECRYPT);
}
</code></pre>
<h2>修改普通socket的代码</h2>
<p>在修改地方加上了 <code>//add</code>或者<code>modified</code>注释<br><strong>服务器端</strong></p>
<pre><code>#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "aes_options.h" //add
int main()
{
int server_fd;
int client_fd;
int len;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int sin_size;
char buffer[BUFSIZ];
// printf("%d",BUFSIZ);
memset(&server_addr, 0, sizeof(server_addr)); //initialize struct
memset(&server_addr, 0, sizeof(client_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(9000);
if((server_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) //create server socket
{
perror("socket create failed");
return 1;
}
if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0) //bind info on server socket
{
perror("bind failed");
return 1;
}
listen(server_fd, 5); //listen port 9000
sin_size = sizeof(struct sockaddr_in);
if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size)) < 0)
{
perror("accept failed");
return 1;
}
printf("accept client %s\n", inet_ntoa(client_addr.sin_addr));
len = send(client_fd, "Welcome to my server\n", 21, 0);
while((len=recv(client_fd, buffer, BUFSIZ, 0)) > 0)
{
char *decryto_string = NULL; //add
decrypt(buffer, &decryto_string, len); //add
printf("%s \n", decryto_string);
if(send(client_fd, decryto_string, len, 0) < 0) //modified
{
perror("send failed");
return 1;
}
}
close(client_fd);
close(server_fd);
return 0;
}
</code></pre>
<p><strong>客户端</strong></p>
<pre><code>#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "aes_options.h" //add
int main()
{
int len;
int client_sockfd;
struct sockaddr_in server_addr;
char buffer[BUFSIZ];
char *encrypt_string = NULL;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(9000);
if((client_sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket create failed");
return 1;
}
if(connect(client_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
{
perror("connect failed");
return 1;
}
printf("connect to server\n");
len = recv(client_sockfd, buffer, BUFSIZ, 0);
buffer[len] = '\0';
printf("%s", buffer);
while(1)
{
printf("enter a data:");
scanf("%s", buffer);
if(!strcmp(buffer,"quit"))
break;
int encrypt_length = encrypt(buffer, &encrypt_string); //add
len = send(client_sockfd, encrypt_string, encrypt_length, 0); //add
len = recv(client_sockfd, buffer, BUFSIZ, 0);
buffer[len] = '\0';
printf("recived:%s \n", buffer);
}
close(client_sockfd);
printf("bye");
return 0;
}
</code></pre>
<h2>解释说明</h2>
<ol>
<li>文件<code>aes_options.h</code> 和<code>aes_options.c</code>里面为两个函数,第一个为加密,第二个为解密.</li>
<li>在socket的两个文件中引入<code>aes_options.h</code>即可使用两个函数..</li>
<li>编译的时候需要执行如下命令:</li>
</ol>
<pre><code>gcc aes_options.c socket_comunication_server.c -o server -lcrypto
gcc aes_options.c socket_comunication_client.c -o client -lcrypto## 标题文字 ##
</code></pre>
Ubuntu下sublime解决中文无法输入的问题
https://segmentfault.com/a/1190000000467286
2014-04-13T19:15:23+08:00
2014-04-13T19:15:23+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
0
<h4>注:</h4>
<ul>
<li>只测试了了fcitx,没有测试ibus</li>
<li>因为不是新手教程,所以安装sublime,fcitx,gcc等等的就不说了</li>
<li>若看不懂请留言</li>
</ul>
<hr>
<h2>下面为实现过程:</h2>
<ul>
<li><strong>copy下列代码,保存为sublime_fix.c</strong></li>
</ul>
<pre><code class="lang-c">#include <gtk/gtk.h>
#include <gdk/gdkx.h>
typedef GdkSegment GdkRegionBox;
struct _GdkRegion
{
long size;
long numRects;
GdkRegionBox *rects;
GdkRegionBox extents;
};
GtkIMContext *local_context;
voidgdk_region_get_clipbox (const GdkRegion *region , GdkRectangle *rectangle)
{
g_return_if_fail (region != NULL);
g_return_if_fail (rectangle != NULL);
rectangle->x = region->extents.x1;
rectangle->y = region->extents.y1;
rectangle->width = region->extents.x2 - region->extents.x1;
rectangle->height = region->extents.y2 - region->extents.y1;
GdkRectangle rect;
rect.x = rectangle->x;
rect.y = rectangle->y;
rect.width = 0;
rect.height = rectangle->height;
if(rectangle->width == 2 && GTK_IS_IM_CONTEXT(local_context)) {
gtk_im_context_set_cursor_location(local_context, rectangle);
}
}
static GdkFilterReturn event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer im_context)
{
XEvent *xev = (XEvent *)xevent;
if(xev->type == KeyRelease && GTK_IS_IM_CONTEXT(im_context)) {
GdkWindow * win = g_object_get_data(G_OBJECT(im_context),"window");
if(GDK_IS_WINDOW(win))
gtk_im_context_set_client_window(im_context, win);
}
return GDK_FILTER_CONTINUE;
}
void gtk_im_context_set_client_window (GtkIMContext *context , GdkWindow *window)
{
GtkIMContextClass *klass;
g_return_if_fail (GTK_IS_IM_CONTEXT (context));
klass = GTK_IM_CONTEXT_GET_CLASS (context);
if (klass->set_client_window)
klass->set_client_window (context, window);
if(!GDK_IS_WINDOW (window))
return;
g_object_set_data(G_OBJECT(context),"window",window);
int width = gdk_window_get_width(window);
int height = gdk_window_get_height(window);
if(width != 0 && height !=0) {
gtk_im_context_focus_in(context);
local_context = context;
}
gdk_window_add_filter (window, event_filter, context);
}
</code></pre>
<ul>
<li>
<p><strong>使用下列命令编译它</strong></p>
<p>gcc -shared -o libsublime-imfix.so sublime_fix.c `pkg-config --libs --cflags gtk+-2.0/` -fPIC</p>
</li>
<li>
<p><strong>添加运行权限给libsublime-imfix.so</strong></p>
<p>chmod +x libsublime-imfix.so</p>
</li>
<li><strong>将编译后的文件libsublime-imfix.so复制到sublime的文件夹下面</strong></li>
<li><strong>在sublime安装目录下新建文件为sublime_sh.sh,copy内容如下:</strong></li>
</ul>
<pre><code class="lang-bash">#!/bin/bash
SUBLIME_HOME="~/software" #你的sublime安装目录
LD_LIB="$SUBLIME_HOME/libsublime-imfix.so"
sh -c "LD_PRELOAD=$LD_LIB $SUBLIME_HOME/sublime $@"
</code></pre>
<ul>
<li><strong>你已经可以通过teminal启动sublime了,运行./sublime_sh.sh即可</strong></li>
<li><strong>若要通过启动器启动sublime,请将你sublime.desktop里面的exec路径修改为sublime_sh.sh所在路径</strong></li>
</ul>
<h2>over</h2>
关于如何安装win7+Ubuntu双系统
https://segmentfault.com/a/1190000000354837
2013-12-08T22:05:11+08:00
2013-12-08T22:05:11+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
1
<h2>写这个博客的目的:</h2>
<p>因为最近有好多的学弟学妹让我帮他们装Ubuntu但是我个人时间实在太少.只好写了这个博客希望一劳永逸...</p>
<h2>工具:</h2>
<ol>
<li>U盘一枚,至少2G以上</li>
<li>Ubuntu live usb制作工具一个 链接:<a rel="nofollow" href="http://unetbootin.cn.uptodown.com/">http://unetbootin.cn.uptodown.com/</a></li>
<li>Ubuntu13.04 iso 一个. 链接:<a rel="nofollow" href="http://mirrors.ustc.edu.cn/ubuntu-releases/13.04/">http://mirrors.ustc.edu.cn/ubuntu-releases/13.04/</a></li>
</ol>
<h2>提示:</h2>
<p>你的磁盘一定要是基本磁盘.不能是动态磁盘.要不然没办法装双系统</p>
<h2>过程:</h2>
<p>注:因为我在linux下没办法截图.</p>
<h3>windows 下的操作</h3>
<ol>
<li>插入你的U盘在USB2.0的串行口上.</li>
<li>运行unetbootin.在里面选择好镜像文件和你插入的U盘的盘号(假定为G盘)</li>
<li>然后点击OK开始制作.大概得4分钟左右..中间会在复制209号文件的时候等待较长时间.</li>
<li>接下来要将windows的一部分磁盘划分出来.右键</li>
<li>右键点击"计算机",选择"管理"选项.</li>
<li>在弹出的界面中选择磁盘管理</li>
<li>在磁盘管理中看看你的哪个磁盘(C盘除外)剩余空间最大.右键点击代表他的那个矩形.</li>
<li>选择"压缩卷".然后在里面填写你要切出来多少空间给Ubuntu.以KB为单位的.</li>
<li>点击OK或者类似的按钮.然后你会发现在哪个长条矩形上出现一个绿色的矩形.就是你切出来的空间了(建议至少50G)</li>
<li>完成之后重启你的电脑.</li>
</ol>
<h3>安装时的操作</h3>
<ol>
<li>在开机的第一个界面快要出来的时候狂按F12,进入boot选择界面.选择USB启动.</li>
<li>会出现一个蓝底白字的界面.选择INSTALL UBUNTU.有两个这个选项.选择哪个都行.</li>
<li>然后进入安装界面.首先会让你选择语言.第一次建议选中文.比较好装.当然英文比较好的话就无所谓了.</li>
<li>选好之后continue,然后第二个界面是检测你是否满足安装需求.至少学要4.5G的硬盘空间。电源插上.其他不要管.继续continue</li>
<li>接下来是选择联网.选择暂时不要联网.</li>
<li>继续continue.接下来这个界面需要特别注意.需要选择something else.就是最后一个选项.(估计问我的那个小朋友应该是在这里跪了的)</li>
<li>然后进入一个分区界面.你会看到好多的分区.但是别怕.首先格式是ntfs的一个都不要动.</li>
<li>然后你会看到你在windows划分出来的那部分空间在这里别标识为free space.对了就是这个.</li>
<li>对这些空间进行操作.选中他.然后点击左下角的哪个+号.然后在弹出来的界面里面填2049(M).然后用在use as(用作)选择为swap.点击ok</li>
<li>接下来等待他刷新之后继续点击free space 然后+号,选择30G(自己算一下成M).然后use as选择为ext 4.这时候下面会出现一个挂载点选项.选择根目录(/).</li>
<li>等待刷新.然后点击free space,+号.将剩下的空间全部填进去.然后use as选择ext4.挂载点选择(/home).</li>
<li>点击install now.然后就开始安装了已经.</li>
<li>这时候会让你填充一些你的用户信息.用户名 密码填好就好了.等待安装完成.</li>
<li>安装完成之后会让你重启。然后重启.重新开机的时候会有一个选择界面让你选择进入哪一个系统.选择Ubuntu就行了.</li>
</ol>
<h2>OVER</h2>
python2.7 查询mysql中文乱码问题
https://segmentfault.com/a/1190000000353533
2013-12-06T14:25:28+08:00
2013-12-06T14:25:28+08:00
LoftySoul
https://segmentfault.com/u/loftysoul
2
<h2>问题:</h2>
<h3>python2.7 查询或者插入中文数据在mysql中的时候出现中文乱码</h3>
<h2>---</h2>
<h2>可能情况:</h2>
<h3>1.mysql数据库各项没有设置编码,默认为'latin'</h3>
<h3>2.使用MySQL.connect的时候没有设置默认编码</h3>
<h3>3.没有设置python的编码,python2.7默认为'ascii'</h3>
<h3>4.没有解码</h3>
<h2>---</h2>
<h2>解决方法:</h2>
<h3>1.设置mysql的编码</h3>
<p>ubuntu执行下列语句:<br />
** sudo vim /etc/mysql/my.cnf **<br />
然后在里面插入语句:</p>
<pre><code class="lang-python">[client]
default-character-set=utf8
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
</code></pre>
<p>退出 vim<br />
重新启动mysql:<br />
** sudo service mysql restart **</p>
<h3>2.在code中设置MySQLdb的连接编码参数</h3>
<pre><code class="lang-python">db=MySQLdb.connect(user='...',db='...',passwd='...',host='...',charset='utf8')
</code></pre>
<h3>3.在code中设置python默认编码</h3>
<pre><code class="lang-python"># -*-coding:utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
</code></pre>
<h3>4.记得要解码</h3>
<pre><code class="lang-python">t = cursor.fetchall()
s = t[0][1].decode('utf-8')
</code></pre>
<h2>over</h2>