要供应互联网做事,当你在开拓代码的时候必须时候保持安全意识。
可能大部分 PHP 脚本都对安全问题都不在意,这很大程度上是由于有大量的无履历程序员在利用这门措辞。
但是,没有情由让你由于对你的代码的不愿定性而导致不一致的安全策略。
当你在做事器上放任何涉及到钱的东西时,就有可能会有人考试测验破解它。
创建一个论坛程序或者任何形式的购物车,被攻击的可能性就上升到了无穷大。

背景

为了确保你的 web 内容安全,这里有一些常规的安全准则:

php如何保证安全生产PHP 平安编程建议 AJAX

别相信表单

攻击表单很大略。
通过利用一个大略的 JavaScript 技巧,你可以限定你的表单只许可在评分域中填写 1 到 5 的数字。
如果有人关闭了他们浏览器的 JavaScript 功能或者提交自定义的表单数据,你客户真个验证就失落败了。

用户紧张通过表单参数和你的脚本交互,因此他们是最大的安全风险。
你该当学到什么呢?在 PHP 脚本中,总是要验证 通报给任何 PHP 脚本的数据。
在本文中,我们向你演示了如何剖析和戒备跨站脚本(XSS)攻击,它可能会挟制用户凭据(乃至更严重)。
你也会看到如何防止会玷污或毁坏你数据的 MySQL 注入攻击。

别相信用户

假定你网站获取的每一份数据都充满了有害的代码。
清理每一部分,即便你相信没有人会考试测验攻击你的站点。

关闭全局变量

你可能会有的最大安全漏洞是启用了 register_globals 配置参数。
幸运的是,PHP 4.2 及往后版本默认关闭了这个配置。
如果打开了 register_globals,你可以在你的 php.ini 文件中通过改变 register_globals 变量为 Off 关闭该功能:

register_globals = Off

1

register_globals = Off

新伎俩式员以为注册全局变量很方便,但他们不会意识到这个设置有多么危险。
一个启用了全局变量的做事器会自动为全局变量赋任何形式的参数。
为了理解它如何事情以及为什么有危险,让我们来看一个例子。

假设你有一个称为 process.php 的脚本,它会向你的数据库插入表单数据。
初始的表单像下面这样:

XHTML

<input name=\"大众username\公众 type=\"大众text\"大众 size=\公众15\公众 maxlength=\"大众64\"大众>

1

<input name=\"大众username\"大众 type=\"大众text\"大众 size=\公众15\"大众 maxlength=\"大众64\"大众>

运行 process.php 的时候,启用了注册全局变量的 PHP 会将该参数赋值到 $username 变量。
这会比通过 $_POST[‘username’]或 $_GET[‘username’] 访问它节省击键次数。
不幸的是,这也会给你留下安全问题,由于 PHP 会设置该变量的值为通过 GET 或 POST 的参数发送到脚本的任何值,如果你没有显示地初始化该变量并且你不肯望任何人去操作它,这就会有一个大问题。

看下面的脚本,如果 $authorized 变量的值为 true,它会给用户显示通过验证的数据。
正常情形下,只有当用户精确通过了这个假想的 authenticated_user() 函数验证,$authorized 变量的值才会被设置为真。
但是如果你启用了 register_globals,任何人都可以发送一个 GET 参数,例如 authorized=1 去覆盖它:

PHP

<?php

// Define $authorized = true only if user is authenticated

if (authenticated_user()) {

$authorized = true;

}

?>

1

2

3

4

5

6

<?php

// Define $authorized = true only if user is authenticated

if (authenticated_user()) {

$authorized = true;

}

?>

这个故事的寓意是,你该当从预定义的做事器变量中获取表单数据。
所有通过 post 表单通报到你 web 页面的数据都会自动保存到一个称为 $_POST 的大数组中,所有的 GET 数据都保存在 $_GET 大数组中。
文件上传信息保存在一个称为 $_FILES 的分外数据中。
其余,还有一个称为 $_REQUEST 的复合变量。

要从一个 POST 方法表单中访问 username 字段,可以利用 $_POST[‘username’]。
如果 username 在 URL 中就利用$_GET[‘username’]。
如果你不愿定值来自哪里,用 $_REQUEST[‘username’]。

PHP

<?php

$post_value = $_POST['post_value'];

$get_value = $_GET['get_value'];

$some_variable = $_REQUEST['some_value'];

?>

1

2

3

4

5

<?php

$post_value = $_POST['post_value'];

$get_value = $_GET['get_value'];

$some_variable = $_REQUEST['some_value'];

?>

$_REQUEST 是 $_GET、$_POST、和 $_COOKIE 数组的结合。
如果你有两个或多个值有相同的参数名称,把稳 PHP 会利用哪个。
默认的顺序是 cookie、POST、然后是 GET。

推举安全配置选项

这里有几个会影响安全功能的 PHP 配置设置。
下面是一些显然该当用于生产做事器的:

register_globals 设置为 offsafe_mode 设置为 offerror_reporting 设置为 off。
如果涌现缺点了,这会向用户浏览器发送可见的缺点报告信息。
对付生产做事器,利用缺点日志代替。
开拓做事器如果在防火墙后面就可以启用缺点日志。
(LCTT 译注:此处据原文逻辑和知识,该当是“开拓做事器如果在防火墙后面就可以启用缺点报告,即 on。
”)停用这些函数:system()、exec()、passthru()、shell_exec()、proc_open()、和 popen()。
open_basedir 为 /tmp(以便保存会话信息)目录和 web 根目录,以便脚本不能访问这些选定区域外的文件。
expose_php 设置为 off。
该功能会向 Apache 头添加包含版本号的 PHP 署名。
allow_url_fopen 设置为 off。
如果你能够把稳你代码中访问文件的办法-也便是你验证所有输入参数,这并不严格须要。
allow_url_include 设置为 off。
对付任何人来说,实在没有明智的情由会想要访问通过 HTTP 包含的文件。

一样平常来说,如果你创造想要利用这些功能的代码,你就不应该相信它。
尤其要小心会利用类似 system() 函数的代码-它险些肯定有缺陷。

启用了这些设置后,让我们来看看一些特定的攻击以及能帮助你保护你做事器的方法。

SQL 注入攻击

由于 PHP 通报到 MySQL 数据库的查询语句是用强大的 SQL 编程措辞编写的,就有了某些人通过在 web 查询参数中利用 MySQL 语句考试测验 SQL 注入攻击的风险。
通过在参数中插入有害的 SQL 代码片段,攻击者会考试测验进入(或毁坏)你的做事器。

如果说你有一个终极会放入变量 $product 的表单参数,你利用了类似下面的 SQL 语句:

$sql = \"大众select from pinfo where product = '$product'\"大众;

1

$sql = \"大众select from pinfo where product = '$product'\"大众;

如果参数是直接从表单中得到的,该当利用 PHP 自带的数据库特定转义函数,类似:

$sql = 'Select from pinfo where product = '\公众'

mysql_real_escape_string($product) . '\公众';

1

2

$sql = 'Select from pinfo where product = '\"大众'

mysql_real_escape_string($product) . '\"大众';

如果不这样做的话,有人大概会把下面的代码段放到表单参数中:

39'; DROP pinfo; SELECT 'FOO

1

39'; DROP pinfo; SELECT 'FOO

那么 $sql 的结果便是:

select product from pinfo where product = '39'; DROP pinfo; SELECT 'FOO'

1

select product from pinfo where product = '39'; DROP pinfo; SELECT 'FOO'

由于分号是 MySQL 的语句分隔符,数据库会运行下面三条语句:

select from pinfo where product = '39'

DROP pinfo

SELECT 'FOO'

1

2

3

select from pinfo where product = '39'

DROP pinfo

SELECT 'FOO'

好了,你丢失了你的表。

把稳实际上 PHP 和 MySQL 不会运行这种分外语法,由于 mysql_query() 函数只许可每个要求处理一个语句。
但是,一个子查询仍旧会生效。

要防止 SQL 注入攻击,做这两件事:

总是验证所有参数。
例如,如果须要一个数字,就要确保它是一个数字。
总是对数据利用 mysql_real_escape_string() 函数转义数据中的任何引号和双引号。

把稳:要自动转义任何表单数据,可以启用魔术引号(Magic Quotes)。

一些 MySQL 毁坏可以通过限定 MySQL 用户权限避免。
任何 MySQL 账户可以限定为只许可对选定的表进行特定类型的查询。
例如,你可以创建只能选择行的 MySQL 用户。
但是,这对付动态数据并不十分有用,其余,如果你有敏感的用户信息,可能某些人能访问个中一些数据,但你并不肯望如此。
例如,一个访问账户数据的用户可能会考试测验注入访问另一个人的账户号码的代码,而不是为当前会话指定的号码。

防止基本的 XSS 攻击

XSS 表示跨站脚本。
不像大部分攻击,该漏洞发生在客户端。
XSS 最常见的基本形式是在用户提交的内容中放入 JavaScript 以便窃取用户 cookie 中的数据。
由于大部分站点利用 cookie 和 session 验证访客,窃取的数据可用于仿照该用户-如果是一个常见的用户账户就会深受麻烦,如果是管理员账户乃至是彻底的惨败。
如果你不在站点中利用 cookie 和 session ID,你的用户就不随意马虎被攻击,但你仍旧该当明白这种攻击是如何事情的。

不像 MySQL 注入攻击,XSS 攻击很难预防。
Yahoo、eBay、Apple、以及 Microsoft 都曾经受 XSS 影响。
只管攻击不包含 PHP,但你可以利用 PHP 来剥离用户数据以防止攻击。
为了防止 XSS 攻击,你该当限定和过滤用户提交给你站点的数据。
正是由于这个缘故原由,大部分在线公告板都不许可在提交的数据中利用 HTML 标签,而是用自定义的标签格式代替,例如 [b] 和 [linkto]。

让我们来看一个如何防止这类攻击的大略脚本。
对付更完善的办理办法,可以利用 SafeHTML,本文的后面部分会谈论到。

PHP

function transform_HTML($string, $length = null) {

// Helps prevent XSS attacks

// Remove dead space.

$string = trim($string);

// Prevent potential Unicode codec problems.

$string = utf8_decode($string);

// HTMLize HTML-specific characters.

$string = htmlentities($string, ENT_NOQUOTES);

$string = str_replace(\公众#\"大众, \"大众#\"大众, $string);

$string = str_replace(\公众%\公众, \"大众%\"大众, $string);

$length = intval($length);

if ($length > 0) {

$string = substr($string, 0, $length);

}

return $string;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

function transform_HTML($string, $length = null) {

// Helps prevent XSS attacks

// Remove dead space.

$string = trim($string);

// Prevent potential Unicode codec problems.

$string = utf8_decode($string);

// HTMLize HTML-specific characters.

$string = htmlentities($string, ENT_NOQUOTES);

$string = str_replace(\"大众#\"大众, \"大众#\公众, $string);

$string = str_replace(\公众%\"大众, \"大众%\公众, $string);

$length = intval($length);

if ($length > 0) {

$string = substr($string, 0, $length);

}

return $string;

}

这个函数将 HTML 特定的字符转换为 HTML 字面字符。
一个浏览器对任何通过这个脚本的 HTML 以非标记的文本呈现。
例如,考虑下面的 HTML 字符串:

<STRONG>Bold Text</STRONG>

1

<STRONG>Bold Text</STRONG>

一样平常情形下,HTML 会显示为:Bold Text

但是,通过 transform_HTML() 后,它就像原始输入一样呈现。
缘故原由是处理的字符串中的标具名符串转换为 HTML 实体。
transform_HTML() 的结果字符串的纯文本看起来像下面这样:

<STRONG>Bold Text</STRONG>

1

<STRONG>Bold Text</STRONG>

该函数的本色是 htmlentities() 函数调用,它会将 <、>、和 & 转换为 <、>、和 &。
只管这会处理大部分的普通攻击,但有履历的 XSS 攻击者有另一莳花招:用十六进制或 UTF-8 编码恶意脚本,而不是采取普通的 ASCII 文本,从而希望能绕过你的过滤器。
他们可以在 URL 的 GET 变量中发送代码,见告浏览器,“这是十六进制代码,你能帮我运行吗?” 一个十六进制例子看起来像这样:

<a href=\公众http://host/a.php?variable=%22%3e %3c%53%43%52%49%50%54%3e%44%6f%73%6f%6d%65%74%68%69%6e%67%6d%61%6c%69%63%69%6f%75%73%3c%2f%53%43%52%49%50%54%3e\"大众>

1

<a href=\公众http://host/a.php?variable=%22%3e %3c%53%43%52%49%50%54%3e%44%6f%73%6f%6d%65%74%68%69%6e%67%6d%61%6c%69%63%69%6f%75%73%3c%2f%53%43%52%49%50%54%3e\"大众>

浏览器渲染这个信息的时候,结果便是:

<a href=\公众http://host/a.php?variable=\公众> <SCRIPT>Dosomethingmalicious</SCRIPT>

1

<a href=\"大众http://host/a.php?variable=\公众> <SCRIPT>Dosomethingmalicious</SCRIPT>

为了防止这种情形,transform_HTML() 采取额外的步骤把 # 和 % 符号转换为它们的实体,从而避免十六进制攻击,并转换 UTF-8 编码的数据。

末了,为了防止某些人用很长的输入超载字符串从而导致某些东西崩溃,你可以添加一个可选的 $length 参数来截取你指定最大长度的字符串。

利用 SafeHTML

之前脚本的问题比较大略,它不许可任何类型的用户标记。
不幸的是,这里有上百种方法能使 JavaScript 跳过用户的过滤器,并且要从用户输入中剥离全部 HTML,还没有方法可以防止这种情形。

当前,没有任何一个脚本能担保无法被破解,只管有一些确实频年夜部分要好。
有白名单和黑名单两种方法加固安全,白名单比较大略而且更加有效。

一个白名单办理方案是 PixelApes 的 SafeHTML 反跨站脚本解析器。

SafeHTML 能识别有效 HTML,能追踪并剥离任何危险标签。
它用另一个称为 HTMLSax 的软件包进行解析。

按照下面步骤安装和利用 SafeHTML:

到 http://pixel-apes.com/safehtml/?page=safehtml 下载最新版本的 SafeHTML。
把文件放到你做事器的类文件夹。
该文件夹包括 SafeHTML 和 HTMLSax 功能所需的所有东西。
在脚本中 include SafeHTML 类文件(safehtml.php)。
创建一个名为 $safehtml 的新 SafeHTML 工具。
用 $safehtml->parse() 方法清理你的数据。

这是一个完全的例子:

<?php

/ If you're storing the HTMLSax3.php in the /classes directory, along

with the safehtml.php script, define XML_HTMLSAX3 as a null string. /

define(XML_HTMLSAX3, '');

// Include the class file.

require_once('classes/safehtml.php');

// Define some sample bad code.

$data = \"大众This data would raise an alert <script>alert('XSS Attack')</script>\"大众;

// Create a safehtml object.

$safehtml = new safehtml();

// Parse and sanitize the data.

$safe_data = $safehtml->parse($data);

// Display result.

echo 'The sanitized data is <br />' . $safe_data;

?>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<?php

/ If you're storing the HTMLSax3.php in the /classes directory, along

with the safehtml.php script, define XML_HTMLSAX3 as a null string. /

define(XML_HTMLSAX3, '');

// Include the class file.

require_once('classes/safehtml.php');

// Define some sample bad code.

$data = \"大众This data would raise an alert <script>alert('XSS Attack')</script>\"大众;

// Create a safehtml object.

$safehtml = new safehtml();

// Parse and sanitize the data.

$safe_data = $safehtml->parse($data);

// Display result.

echo 'The sanitized data is <br />' . $safe_data;

?>

如果你想清理脚本中的任何其它数据,你不须要创建一个新的工具;在你的全体脚本中只须要利用 $safehtml->parse() 方法。

什么可能会涌现问题?

你可能犯的最大缺点是假设这个类能完备避免 XSS 攻击。
SafeHTML 是一个相称繁芜的脚本,险些能检讨所有事情,但没有什么是能担保的。
你仍旧须要对你的站点做参数验证。
例如,该类不能检讨给定变量的长度以确保能适应数据库的字段。
它也不检讨缓冲溢出问题。

XSS 攻击者很有创造力,他们利用各种各样的方法来考试测验达到他们的目标。
可以阅读 RSnake 的 XSS 教程http://ha.ckers.org/xss.html ,看一下这里有多少种方法考试测验使代码跳过过滤器。
SafeHTML 项目有很好的程序员一贯在考试测验阻挡 XSS 攻击,但无法担保某些人不会想起一些奇怪和新奇的方法来跳过过滤器。

把稳:XSS 攻击严重影响的一个例子 http://namb.la/popular/tech.html,个中显示了如何一步一步创建一个让 MySpace 做事器过载的 JavaScript XSS 蠕虫。

用单向哈希保护数据

该脚本对输入的数据进行单向转换,换句话说,它能对某人的密码产生哈希署名,但不能解码得到原始密码。
为什么你希望这样呢?运用程序会存储密码。
一个管理员不须要知道用户的密码,事实上,只有用户知道他/她自己的密码是个好主张。
系统(也仅有系统)该当能识别一个精确的密码;这是 Unix 多年来的密码安全模型。
单向密码安全按照下面的办法事情:

当一个用户或管理员创建或变动一个账户密码时,系统对密码进行哈希并保存结果。
主机系统会丢弃明文密码。
当用户通过任何办法登录到系统时,再次对输入的密码进行哈希。
主机系统丢弃输入的明文密码。
当前新哈希的密码和之前保存的哈希比较较。
如果哈希的密码相匹配,系统就会付与访问权限。

主机系统完成这些并不须要知道原始密码;事实上,原始密码完备无所谓。
一个副浸染是,如果某人侵入系统并盗取了密码数据库,入侵者会得到很多哈希后的密码,但无法把它们反向转换为原始密码。
当然,给足够韶光、打算能力,以及弱用户密码,一个攻击者还是有可能采取字典攻击找出密码。
因此,别轻易让人碰你的密码数据库,如果确实有人这样做了,让每个用户变动他们的密码。

加密 Vs 哈希

技能上来来说,哈希过程并不是加密。
哈希和加密是不同的,这有两个情由:

不像加密,哈希数据不能被解密。

是有可能(但非常罕见)两个不同的字符串会产生相同的哈希。
并不能担保哈希是唯一的,因此别像数据库中的唯一键那样利用哈希。

function hash_ish($string) {

return md5($string);

}

1

2

3

function hash_ish($string) {

return md5($string);

}

上面的 md5() 函数基于 RSA 数据安全公司的择要算法(即 MD5)返回一个由 32 个字符组成的十六进制串。
然后你可以将那个 32 位字符串插入到数据库中和另一个 md5 字符串比较较,或者直接用这 32 个字符。

破解脚本

险些不可能解密 MD5 数据。
或者说很难。
但是,你仍旧须要好的密码,由于用一全体字典天生哈希数据库仍旧很大略。
有一些在线 MD5 字典,当你输入 06d80eb0c50b49a509b49f2424e8c805 后会得到结果 “dog”。
因此,只管技能上 MD5 不能被解密,这里仍旧有漏洞,如果某人得到了你的密码数据库,你可以肯定他们肯定会利用 MD5 字典破译。
因此,当你创建基于密码的系统的时候尤其要把稳密码长度(最小 6 个字符,8 个或许会更好)和包括字母和数字。
并确保这个密码不在字典中。

用 Mcrypt 加密数据

如果你不须要以可阅读形式查看密码,采取 MD5 就足够了。
不幸的是,这里并不总是有可选项,如果你供应以加密形式存储某人的信用卡信息,你可能须要在后面的某个地方进行解密。

最早的一个办理方案是 Mcrypt 模块,这是一个用于许可 PHP 高速加密的插件。
Mcrypt 库供应了超过 30 种用于加密的打算方法,并且供应口令确保只有你(或者你的用户)可以解密数据。

让我们来看看利用方法。
下面的脚本包含了利用 Mcrypt 加密和解密数据的函数:

<?php

$data = \公众Stuff you want encrypted\"大众;

$key = \"大众Secret passphrase used to encrypt your data\公众;

$cipher = \"大众MCRYPT_SERPENT_256\"大众;

$mode = \"大众MCRYPT_MODE_CBC\"大众;

function encrypt($data, $key, $cipher, $mode) {

// Encrypt data

return (string)

base64_encode

(

mcrypt_encrypt

(

$cipher,

substr(md5($key),0,mcrypt_get_key_size($cipher, $mode)),

$data,

$mode,

substr(md5($key),0,mcrypt_get_block_size($cipher, $mode))

)

);

}

function decrypt($data, $key, $cipher, $mode) {

// Decrypt data

return (string)

mcrypt_decrypt

(

$cipher,

substr(md5($key),0,mcrypt_get_key_size($cipher, $mode)),

base64_decode($data),

$mode,

substr(md5($key),0,mcrypt_get_block_size($cipher, $mode))

);

}

?>

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

<?php

$data = \"大众Stuff you want encrypted\公众;

$key = \"大众Secret passphrase used to encrypt your data\"大众;

$cipher = \公众MCRYPT_SERPENT_256\"大众;

$mode = \公众MCRYPT_MODE_CBC\"大众;

function encrypt($data, $key, $cipher, $mode) {

// Encrypt data

return (string)

base64_encode

(

mcrypt_encrypt

(

$cipher,

substr(md5($key),0,mcrypt_get_key_size($cipher, $mode)),

$data,

$mode,

substr(md5($key),0,mcrypt_get_block_size($cipher, $mode))

)

);

}

function decrypt($data, $key, $cipher, $mode) {

// Decrypt data

return (string)

mcrypt_decrypt

(

$cipher,

substr(md5($key),0,mcrypt_get_key_size($cipher, $mode)),

base64_decode($data),

$mode,

substr(md5($key),0,mcrypt_get_block_size($cipher, $mode))

);

}

?>

mcrypt() 函数须要几个信息:

须要加密的数据用于加密和解锁数据的口令,也称为键。
用于加密数据的打算方法,也便是用于加密数据的算法。
该脚本利用了 MCRYPT_SERPENT_256,但你可以从很多算法中选择,包括 MCRYPT_TWOFISH192、MCRYPT_RC2、MCRYPT_DES、和 MCRYPT_LOKI97。
加密数据的模式。
这里有几个你可以利用的模式,包括电子密码本(Electronic Codebook) 和加密反馈(Cipher Feedback)。
该脚本利用 MCRYPT_MODE_CBC 密码块链接。
一个 初始化向量-也称为 IV 或者种子,用于为加密算法设置种子的额外二进制位。
也便是使算法更难于破解的额外信息。
键和 IV 字符串的长度,这可能随着加密和块而不同。
利用 mcrypt_get_key_size() 和 mcrypt_get_block_size() 函数获取得当的长度;然后用 substr() 函数将键的值截取为得当的长度。
(如果键的长度比哀求的短,别担心,Mcrypt 会用 0 添补。

如果有人盗取了你的数据和短语,他们只能一个个考试测验加密算法直到找到精确的那一个。
因此,在利用它之前我们通过对键利用md5() 函数增加安全,就算他们获取了数据和短语,入侵者也不能得到想要的东西。

入侵者同时须要函数,数据和口令,如果真是如此,他们可能得到了对你做事器的完全访问,你只能大洗濯了。

这里还有一个数据存储格式的小问题。
Mcrypt 以难懂的二进制形式返回加密后的数据,这使得当你将其存储到 MySQL 字段的时候可能涌现恐怖缺点。
因此,我们利用 base64encode() 和 base64decode() 函数转换为和 SQL 兼容的字母格式和可检索行。

破解脚本

除了实验多种加密方法,你还可以在脚本中添加一些便利。
例如,不用每次都供应键和模式,而是在包含的文件中声明为全局常量。

天生随机密码

随机(但难以预测)字符串在用户安全中很主要。
例如,如果某人丢失了密码并且你利用 MD5 哈希,你不可能,也不肯望查找回来。
而是该当天生一个安全的随机密码并发送给用户。
为了访问你站点的做事,其余一个用于天生随机数字的运用程序会创建有效链接。
下面是创建密码的一个函数:

<?php

function make_password($num_chars) {

if ((is_numeric($num_chars)) &&

($num_chars > 0) &&

(! is_null($num_chars))) {

$password = '';

$accepted_chars = 'abcdefghijklmnopqrstuvwxyz1234567890';

// Seed the generator if necessary.

srand(((int)((double)microtime()1000003)) );

for ($i=0; $i<=$num_chars; $i++) {

$random_number = rand(0, (strlen($accepted_chars) -1));

$password .= $accepted_chars[$random_number] ;

}

return $password;

}

}

?>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<?php

function make_password($num_chars) {

if ((is_numeric($num_chars)) &&

($num_chars > 0) &&

(! is_null($num_chars))) {

$password = '';

$accepted_chars = 'abcdefghijklmnopqrstuvwxyz1234567890';

// Seed the generator if necessary.

srand(((int)((double)microtime()1000003)) );

for ($i=0; $i<=$num_chars; $i++) {

$random_number = rand(0, (strlen($accepted_chars) -1));

$password .= $accepted_chars[$random_number] ;

}

return $password;

}

}

?>

利用脚本

make_password() 函数返回一个字符串,因此你须要做的便是供应字符串的长度作为参数:

<?php

$fifteen_character_password = make_password(15);

?>

1

2

3

<?php

$fifteen_character_password = make_password(15);

?>

函数按照下面步骤事情:

函数确保 $num_chars 是非零的正整数。
函数初始化 $accepted_chars 变量为密码可能包含的字符列表。
该脚本利用所有小写字母和数字 0 到 9,但你可以利用你喜好的任何字符凑集。
(LCTT 译注:有时候为了便于肉眼识别,你可以将个中的 0 和 O,1 和 l 之类的都去掉。
)随机数天生器须要一个种子,从而得到一系列类随机值(PHP 4.2 及之后版本中并不须要,会自动播种)。
函数循环 $num_chars 次,每次迭代天生密码中的一个字符。
对付每个新字符,脚本查看 $accepted_chars 的长度,选择 0 和长度之间的一个数字,然后添加 $accepted_chars中该数字为索引值的字符到 $password。
循环结束后,函数返回 $password。

转载地址:https://linux.cn/article-5868-1.html