分类 Web开发 下的文章

如何选择面向对象编程与面向过程编程?

可能我们脑海里天生就有面向过程编程的思想,大致就是把一件事情分成几步,一步一步地完成。不假思索写出来的代码,自然就是面向过程的。

对于面向过程编程,变量(数据)与函数(行为)是分开的,它们都被安排在某个模块(文件)里。模块就好像是一个对象(类),因此,面向过程编程就好比在一个默认的类中编程,而这个类往往不被注意到。

对象同时包含数据和行为。如果只考虑数据,使用列表、字典等 Python 数据结构即可。如果只关注行为而不存储任何数据,那一个简单的函数更合适。

听起来有点枯燥,我们通过例子来理解。

计算多边形的周长

面向过程

通常来说,我们会以一个存储着各个顶点的列表来代表多边形。每个顶点以一个二维元组(x, y)建模,该元组描述顶点的位置坐标。

square = [(1, 1), (1, 2), (2, 2), (2, 1)]

计算周长,我们只需要计算相邻两个顶点之间的距离,然后加起来。因此需要一个计算两点之间的距离的函数。编码如下:

import math

def distance(p1, p2):
    return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)

def perimeter(polygon):
    perimeter = 0
    points = polygon + [polygon[0]]
    for i in range(len(polygon)):
        perimeter += distance(points[i], points[i+1])
    return perimeter

这是面向过程的解决办法,调用方法如下:

square = [(1, 1), (1, 2), (2, 2), (2, 1)]
perimeter(square)

4.0

面向对象

上面的函数已经很简洁明了,但不妨来看看面向对象的版本是怎样的。

import math

class Point(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def distance(self, p2):
        return math.sqrt((self.x - p2.x) ** 2 + (self.y - p2.y) ** 2)

class Polygon(object):

    def __init__(self):
        self.vertices = []

    def add_point(self, point):
        self.vertices.append(point)

    def perimeter(self):
        perimeter = 0
        points = self.vertices + [self.vertices[0]]
        for i in range(len(self.vertices)):
            perimeter += points[i].distance(points[i+1])
        return perimeter

这段代码比上面的面向过程版本长了很多,几乎是上面的两倍。我们先来看看它是如何调用的。

square = Polygon()
square.add_point(Point(1, 1))
square.add_point(Point(1, 2))
square.add_point(Point(2, 2))
square.add_point(Point(2, 1))
square.perimeter()

4.0

是不是通俗易懂,它比函数版本的代码更易读。对于函数版本的代码,我们可能需要写更多的文档以表明它的用法。

我们还可以对 Polygon 类进行优化,使它更容易使用,让它像函数版本那样接受一个元组的列表。

def __init__(self, points=[]):
    self.vertices = []
    for point in points:
        if isinstance(point, tuple):
            point = Point(*point)
        self.vertices.append(point)

如果我们要为多边形增加一些特征,如 color 或者 texture,将这些数据封装进类会变得更有意义。一般来讲,拥有复杂的数据集,需要对它进行特定操作,这时使用具有属性和方法的类会很有帮助。它不仅可以使代码易读,还可以使逻辑紧凑。

如何选择

在一个具体的场景里,如果只需要计算多边形的周长,一个函数可能是最简单、最快的开发方法。但是如果我们需要对多边形进行多种处理(计算周长、面积、和其它多边形的交点等),那么我们需要一个对象来满足这些需求。所以,对于较复杂的问题,一般采用面向对象编程。

用户登录过程中密码传输的安全分析

密码,属于个人机密。最好除本人以外,不让任何人知道。

对于某个网络应用的密码,需要保存到服务提供方的服务器,因此必须加密。最好采用不可逆加密,以确保服务提供方也无法知道原始密码。另外一方面也是为了防止拖库(数据库整体泄露)。所以服务端保存的密码,一般是对原始密码进行哈希处理的结果。

分析

密码在传输过程中要加密

一般网络攻击的入口有三处:客户端、传输过程、服务端。本文主要是分析用户登录的数据在传输过程中被攻击的情况。这也是黑客最容易下手的地方。现在连接网络基本都通过 wifi 的方式,最常见的是电脑或者手机连接到陌生的网络(公共 wifi)。那么 wifi 提供方轻而易举就可以监听到用户所有的网络请求,主要是实施抓包和重放攻击(Replay Attacks)。

所以密码在传输过程中也需要加密,这就解决了明文密码在传输过程中被泄露的问题。

请求参数一次有效

重放攻击又叫重播攻击、回放攻击,意思是将用户发送的有效请求再发送一次,以欺骗服务器。(如取得登录凭据。)解决办法是确保请求参数使用过一次即失效,使得重发请求失效。

解决方案

1. 不使用 https 协议的情况

通过随机识别码来防止重放攻击。在进行登录请求前,先请求获得一个随机识别码(request_code),在服务端确保产生一个在有效期内唯一的随机识别码,随机识别码在服务端过期时间设置为 1 分钟。

登录请求的参数中增加随机识别码参数,密码使用 md5 加密。然后对参数进行签名,签名算法事先约定好。签名是为了防止参数被修改。那么登录请求的参数如下:

/api/login/?username=zhangsan&password=md5(pwd)&request_code=4321&sign=xxxxxxxxxx

加密与签名建议使用 RSA 算法。

也可以将每个请求的 body 进行加密,使用对称加密算法。在客户端启动或者初始化时,向服务端请求获取对称加密算法的密钥,该密钥是经过 RSA 加密的,使用时解密出该密钥。(当然,对称密钥要足够复杂。否则,黑客将跳过 RSA 直接攻击对称加密部分。)

2. 使用 https 协议

由于 https 本身已经具有加密和防重放攻击的功能,所以购买证书部署好即可。但是 https 仍然有可能被攻破解,所以在上面的方案基础上增加 https 协议,是最为稳妥的方案。

注:对于浏览器,也可以通过 js 实现 md5 等哈希算法以及 RSA 加解密。

虚拟机 VMware Player 使用笔记

VMware Player

VMware Player 是 VMware Workstation 的精简版,轻量级的虚拟机。它和 VirtualBox 差不多,占用系统资源小,安装简单。

先去官方网站下载 VMware Player,我下载的是 7.1.0 版本,大小只有 75 M左右。这个版本是多语言版,选择中文即可。

安装完后,新建一个虚拟机,设置与其它虚拟机软件一样,大同小异。事先下载好需要安装的系统的 iso 文件。然后在虚拟机设置中,点选 CD/DVD,看到右边的连接,点击“使用 ISO 镜像文件”,然后浏览选择本地已下载好的镜像文件。

设置中的网络适配器,一般默认为 NAT。安装好系统后,如果无法连网,则可以选择桥接网络,再重启虚拟系统。

如果发现光标在虚拟机界面中,无法移出,可以使用 Ctrl+Alt 释放光标。

CentOS 6.4 桌面版

我安装的系统是 CentOS-6.4-x86_64-LiveCD.iso, 配置是 1 核、 1G 内存。

需要高级功能,可以根据软件状态栏的提示安装 VMware Tools。如果是 Linux 系统,需要解压安装包,并且使用 root 权限执行安装程序。我的系统上,安装时间稍长,大约 5 分钟。查看系统负载,已经接近 1。安装成功后,可以在宿主机与虚拟机之间拖放复制文件,同时虚拟机的屏幕分辨率也会与宿主机一致。

CentOS 这个版本默认不支持中文输入,可以通过以下步骤来添加中文输入的支持。

在命令行中使用 root 权限执行如下命令

yum install "@Chinese Support" 

它会下载并安装支持中文的软件。然后在 System -> Preferences 会看到 Input Method 选项。点击打开对话框,然后点击 Enable input method feature 并选择 Use IBus (recommended)。然后进行添加输入法等操作。最后需要重启操作系统。

Git 学习笔记

0. 概念

工作目录(Working directory):本地可见的文件,没有被 Git 系统所管理。工作目录的内容是你当前看到的,也是最新的。

暂存区/索引区(Stage/Index):存放工作目录中那些你打算提交到版本库的变更,Git 并没有把你所添加的文件放入版本库中,而是对内容进行 hash 后生成了一个编号。相当于告诉 Git,我有一个编号为 xxxxx 的文件将要提交。

本地版本库(Repository/History/HEAD):保存着被提交的各个版本。

远程仓库(Remote Repository):是本地仓库的异地备份。

1. 基本操作

请输入图片描述

查看当前状态
git status

会显示未缓存(未索引)的文件,以及未提交的文件。

添加与提交
git add <file>...
git add *
git commit -m "<comment>"
推送到远程仓库
git push [origin master]

说明:将本地 master 分支推入远端的 origin。

如果本地仓库不是克隆过来的,并欲将你的仓库连接到某个远程服务器,可以使用如下命令为远端仓库添加 orgin:

git remote add origin <server>

如此你就能够将你的改动推送到所添加的服务器上去了。

2. 取消已被 Git 初始化(git init)的目录

删除该目录下 .git 文件夹即可。

3. 撤销本地修改

git checkout -- <filename>

此命令会使用 HEAD 中的最新内容替换掉工作目录中的文件。已添加到暂存区的文件不会受到影响,即不变。(当然,已经提交的文件更不会变。)

对于已缓存的文件,可以先撤销缓存(Unstage),再使用上面的命令来取消修改:

git reset HEAD *
git reset HEAD <filename>

4. 撤销提交

git reset --hard <commit_id>

回退到本地最新版本(或某个指定的版本),本地之前修改的未缓存的都会被覆盖掉。

5. 删除文件&文件重命名

删除文件
git rm <filename>
git rm -r <foldername>

rm 与 add 类似,都是将改动缓存起来,即已经添加到暂存区,下一步需要提交。rm 不仅会在 Git 系统中删除文件,它还会自动将物理文件删除。

文件重命名
git mv <filename> <newfilename>

mv 与 add 类似,也是将改动缓存起来,即已经添加到暂存区,下一步需要提交。mv 不仅会在 Git 系统中重命名文件,还会将物理文件重命名。

6. 补充提交

有时候已经提交了,但发现这次提交不完整,还有修改需要在这一次中提交。在没有推送(PUSH)到远端的情况下可用如下命令补交:

git commit --amend -C HEAD

--amend 是重写提交历史,-C 是重用某次提交的提交信息。

7. 命令别名

git config --global alias.(name) "(command)"

括号部分替换为别名和对应的命令。它实际是将这个设置写入配置文件 .gitconfig,可以使用如下命令查看配置文件:

git config --global --list

例如设置 切换分支 命令的别名:

git config --global alias.co "checkout"

那此后就可以这样来切换分支:

git co branch_x

其中 branch_x 为某分支名称。

8. 删除未跟踪的文件

git clean -df
git clean -f

参数说明:-d 删除未跟踪目录,-f 删除未跟踪的文件。

如果想在删除前查看哪些文件将会被删除,可使用下面的命令:

git clean -dn

参考资料:

图解Git

Sublime Text 使用技巧

Sublime Text 是一款优秀的代码编辑器,特别适合于 Linux 系统下 Python 编码。

掌握一些使用技巧,能大大提高开发效率。(在 Ubuntu 系统中,从官网下载,解压即可使用,无需要安装。)

1. 中文输入的问题

在 Linux 系统下开发,可以正常显示中文,但是无法输入中文,就好像输入法此时无效。

使用一个叫 InputHelper 的插件可以很好地解决这个问题。安装和使用都非常简单:

cd ~/.config/sublime-text-2/Packages
git clone https://github.com/xgenvn/InputHelper.git

两个命令就安装好了。使用方法:

按 Ctrl+Shift+Z 组合键会呼出一个输入框,输入中文后,按 Enter 即可。

也有人用别的方法实现中文的输入,如安装 fcitx 输入法平台,可以直接输入中文,但很多人采用此方法没有成功。

2. 如何将缩进改为空格

在 Python 开发时,建议采用 4 个空格作为一个缩进单位。如果 Sublime Text 默认使用的是 Tab,可以将它改为空格。

打开配置文件 Preferences > Settings - Default:

// The number of spaces a tab is considered equal to
"tab_size": 4,

// Set to true to insert spaces when tab is pressed
"translate_tabs_to_spaces": true,

如上配置即可。

3. 快捷键

完整的快捷键参见 Preferences > Key Bindings - Default。

同时编辑多行: 选中多行 > Ctrl + Shift + L (按 Esc 退出该状态)
文件切换/查找文件:Ctrl + P (再按该快捷键或 Esc 退出该状态)
查找函数:Ctrl + P > 输入 @ (输入冒号和数字可以跳转到指定的行),或者直接使用 Ctrl + R
搜索与替换: Ctrl + F 搜索,Ctrl + H 替换
打开控制台:Ctrl + ` (Python 交互控制台)
选择文本:Ctrl + ←/→ 逐词移动,Ctrl + Shift + ←/→ 逐词选择
移动当前行:Ctrl + Shift + ↑/↓
合并多行数组:Ctrl + J
选择所有出现的某个词:Alt + F3

打开完整的命令面板:Ctrl + Shift + P (以实现完全的键盘控制)

4. 扩展包管理器

扩展包管理请参考:http://www.iplaysoft.com/sublimetext.html

5. 配置

修改 settings - user, 如:

{
    "font_face": "Courier New",  //比较适合代码阅读
    "font_size": 14,
    "translate_tabs_to_spaces": true  //自动将 tab 转换为 空格
}

6. 其它

有一篇详细介绍 Sublime Text 使用的文章《Sublime Text 全程指引》。