时间:2022-12-30 12:24:01
前言在撰写本文之后的几年里,许多黑客都将目标锁定在受密码保护的网站上。 保存客户密码成为许多讨论的主题,其中有些是有用的,有些是被误解的。 当然,没有人用明文存储客户端密码,但许多尝试的解决方案(消息摘要、加密等)都比明文稍好。 有关保存密码的相关文章,请参阅PHP的密码散列。 以下讨论和文章中的“稍后:关于密码保存”已过时,不应用作APP讨论的基础。 介绍新PHP开发人员常见的设计模式问题。 “您如何处理客户端注册和登录? ’在所有框架和CMS中完成,使用了类似的模式。 在本文中,我们逐步构建了模式,以便可以看到代码各部分的内容。 此示例说明客户端是否已使用PHP会话处理程序登录。 此外,还使用了cookie来“记住”客户端已登录,并使用了包含客户端的数据库表信息。 通过实现此设计模式,可以使用一行PHP代码对网页进行密码保护,如下所示:
access_control (;

您还可以通过以下方式测试客户端登录: 实际上不需要登录。
访问控制( true )/*clientisalreadyloggedin(/}
正文的最后有一些注释和后记。 如果你有时间,你可能需要向下滚动并马上阅读。 尝试使用此设计时,将更详细地讨论可能出现的问题。 然后回来继续。 约定和标准1 .我同意在所有页面上使用session_start ( )的约定。 没有例外。 也可以在公共脚本的顶部添加session_start ),以便网站的每个页面都可以这样开始。 此脚本包含在所有页面脚本的顶部。
PHP require _ once ( ray _ ee _ config.PHP ); //PHP AND HTML CODE FOLLOWS BELOW
“配置”脚本还便于放置数据库连接、选择代码和define (语句、局部变量、类和函数)。 你可能知道将这些通用元素包含在一个数据库中。 单一的、容易搜索的脚本。 2 .我同意在要保护的每一页的非常顶部添加access_control )语句的承诺。 为什么要戳? 因为必须使用header ( )函数,并且这是HTTP的协议限制,所以在所有浏览器输出之前必须呈现并完成所有标头。 header ) )语句失败,如果违反此协议,脚本将失败。 创建浏览器输出时,有几种方法可以遵循此协议。 PHP函数ob_start ) )有助于解决这个问题。 但是,此处的任务不需要ob_start )。 只有在标头命令全部完成后,才能按正确的顺序处理数据并生成浏览器输出。 了解这些之后,让我们开始构建访问控制系统框架。 公共元素-配置脚本的第一步是创建一个“配置”脚本,其中包含所有web脚本所需的公共元素。 需要定制一些这些示例。 特别是,在以下脚本的第15-20行附近添加自己的数据库凭据。 有了这些信息,您应该可以在自己的服务器上安装和运行这些代码片段,以查看实际的“部件移动”。 如果有数据库证书,请连接到数据库服务器并选择数据库。 第21-34行。 让我们看一下在第36行定义的access_control (函数。 第一步是保存客户端的入口积分,以便在客户端验证后可以返回到正确的页面。 请使用REQUEST_URI字符串而不是PHP_SELF,因为REQUEST_URI不仅包含URL地址,还包含URL参数。 PHP_SELF只有URL地址。 然后测试会话UID变量。 如果设置了此选项,则客户端已登录,无需进一步处理,返回TRUE。 如果客户端未登录,则仅转至此函数的下一行。 如果客户端未登录,请检查$ test参数。 缺省设置为FALSE,但如果调用脚本并将其设置为TRUE,则会返回一条指示客户端未登录的消息。 如果客户端未登录,则这不是测试。 页面需要保护。 因此,我们将客户端浏览器重定向到登录页面,然后退出该脚本。 我们还需要函数来完成我们的工作。 设置“记住我”cookie的函数。 这个定义从第53行开始。 将Cookie的" uuk "命名为“唯一的用户密钥”,生存期取决于在第10行中定义的常量REMEMBER的定义。 有关setcookie ( )的详细信息,请参阅PHP联机文档。 http://PHP.net/manual/en/function.setcookie.PHP具有一个“config”框架,可以从第80行开始执行。我们首先测试的是会话数组如果有,则有经过验证的客户端,不需要其他处理。 但是,即使未设置$ _SESSION [“ uid”],也可以通过“uuk” cookie中的信息记住客户端。 如果设置了cookie,则可以通过在数据库中搜索客户端并自动完成登录来实现“记住”承诺。 $ _COOKIE数组包含存储在客户端计算机上的数据,因此必须将其视为“污染”外部数据。 因此,最少的检查是在查询中使用mysqli : real_escape_string ( )之前运行数据。 尝试使用这样提供的数据在查询用户表中查找与此唯一用户密钥匹配的UID。 如果在数据库中找到UID,则会将其复制到会话数组(第101行),并且客户端已登录。 最后一步是在第104行中调用Remember_me ( )函数来扩展客户端的内存。
在这里调用这个功能,可以被记住,可以反复记住经常访问网站的客户,也可以永远记住。 这是一个常见的“配置”脚本。
PHP//ray _ ee _ config.PHP//whenwearedebuggingourcode,WE WANT TO SEE ALL THE ERRORS! error_reporting(e_all; //requiredforphp 5.1 date _ default _ time zone _ set ( America/Chicago ); //thelifeofthe ' remember me ' cookie define (,60*60*24*7); //oneweekinseconds//wewanttostartthesessiononeverypagesession _ start (; //connectionandselectionvariablesforthedatabase $ db _ host=' localhost '; //PROBABLY THIS IS OK$db_name=' '; //getthesefromyourhostingcompany $ db _ user=' '; $db_word=' '; //openaconnectiontothedatabaseserverandselectthedb $ mysqli=new mysqli ( $ db _ host,$db_user,$db_word, $ db//didtheconnect/selectworkorfailif ( $ mysqli-connect _ errno ) $ err=' connect fail:'.$ mysqli-conect _ errno (/definetheaccesscontrolfunctionfunctionaccess _ control ) $test=false )/rememberhowwegothere $ _ sesion [ ' esssion //ifwearenotloggedin-respondtothetestrequestif ( $ test )返回假; //IF THIS IS NOT A TEST,redirecttocallforaloginheader ( location:ray _ ee _ log in.PHP ); 退出; //define the ' remember me ' cookiefunctionfunctionfunctionremember _ me ( $ uuk ) )//construct a ' remember me ' cookiewithththeuning $cookie_expires=time(date ) ' z ) REMEMBER; $cookie_path='/'; $cookie_domain=NULL; $cookie_secure=FALSE; $cookie_http=TRUE; //hidecookiefromjavascript ( PHP 5.2 )/see http://PHP.net/manual/en/function.setcookie.PHP setcookie ) $cookie ) $cookie_expires,$cookie_path,$cookie_domain,$cookie_secure,$cookie_http; //determineiftheclientisalreadyloggedinbecauseofthesessionarrayif (! isset($_session['uid'] )//determineiftheclientisalreadyloggedinbecauseof ' remember me ' feature if ( isset ) $ ) $RES=$MySQLI-query($SQL ); //ifthequerysucceededif($RES )//thereshouldbeonerow $ num=$ RES-num _ rows; if($num ) )/retrievetherowfromthequeryresultsset $ row=$ RES-fetch _ assoc ); //store the user-idinthesessionarray $ _ session [ ' uid ' ]=$ row [ ' uid ' ]; //extend the ' remember me ' cookie remember _ me $ uuk; } } }}
数据库表-我们为客户数据模型编写了一个常见的“配置”脚本。 是时候创建对访问控制功能有用的数据库表了。 下面“编写代码”部分中的代码应该很好。 EE_userTable有三列。 这些是" uid "列中的用户id、" pwd "列中的用户密码和" uuk "列中的用户特定密钥。 在现实生活中,永远不会用明文保存密码。保存密码的抽象版本或加密版本。 (见本文最后一节。 但是,在本例中,通过以明文处理密码,可以使设计更容易理解。
PHP///ray _ ee _ create.PHP require _ once ( ray _ ee _ config.PHP ); //activatethistodroptheoldee _ usertable//$ mysqli-query ( ' drop table ee _ usertable ' ); $ SQL=' create table ee _ usertable ( keyintnotnotnullauto _ increment,uidvarchar(16 ) NOT NULL DEFAULT ',PWDvarchar )。 UKVarchar(32 ) NOT NULL DEFAULT ',primarykey ) ); if (! $RES=$mysqli-query($SQL ) ) trigger _ error ( $ mysqli-error,E_USER_ERROR );
测试工具此时,建议您为新的脚本和新的数据库表创建测试平台。 测试需要两个脚本。 一个完全由访问控制。 另一个是公共页面,用于仅测试访问控制,并使用响应确定要创建的输出。 这两个脚本满足了这些要求。
PHP//ray _ ee _ controlled.PHP require _ once ( ray _ ee _ config.PHP ); //accesstothispageiscontrolled $ uid=access _ control (; echo '
hello $ uidandwelcometotheaccesscontrolledpage ';
PHP///ray _ ee _ public.PHP require _ once ( ray _ ee _ config.PHP ); //accesstothispageistestedbutnotcontrolledif ( $ uid=access _ control ) true ) ( { echo )。
hello $ uidandwelcometothepublicpage '; }else{ echo
HELLO STRANGER.'; echo '
youmightwanttoregisteronthissite '; echo '
IF YOU ARE ALREADY REGISTERED,YOU CAN LOG IN HERE '; () ) ) ) )。
方便客户-如果注册页数很少,可以使用phpMyAdmin手动注册所有用户,但如果有面向公众的网站,则需要做很多工作。 相反,他们想创建一个页面,让用户注册自己。 在下一页完成注册工作。 补充说明:如果您想稍微扩展一下这个概念,这里的EE文章可能会有帮助。 http://www.experts-exchange.com/web _开发吨/web _ lang uages-stands/PHP/a _ 3939-reg中istration-和- reg 使用第二行中的方法加载配置脚本require _ once ( ' ray _ ee _ config.PHP )。 因为脚本无法使用include ) )函数的require格式。由于配置文件包含函数定义,并且尝试重新定义PHP函数会导致致命错误,因此使用了include ( ) )函数的格式。 要开始注册过程,请乐观地将$ err变量设置为NULL (第5行),假设没有错误。 你可以稍后检查那个有没有错误。 然后检查$ _POST数组,以查看是否有处理注册所需的所有信息。 如果尚未注册信息,脚本将落在第53行,并显示注册表。 如果表格中包含所有注册信息,请尝试创建客户记录。 创建客户记录的第一步是清理外部输入。 除了这里的基础知识,我们什么也没做; 在现实生活中,可能会有更广泛的过滤和测试。 但是,此示例只通过转义从表单输入接收到的三个文本字段来保护数据库。 第一个重要的测试是验证两个密码字段是否匹配。 这是因为客户端已填写了type=“ password”的表单输入字段,浏览器在输入时会隐藏输入内容。 为了让客户满意,请她输入两次密码,并确认是否一致。 如果她用同样的方法输入了两次密码,可以肯定的是,由于打字错误而伪造的密码不会分配给她的账户。 如果不匹配,请在$ err变量中添加错误消息。 然后检查数据库以确定是否正在使用UID。 在这种情况下,将其视为错误,并通过在$ err变量的末尾添加错误消息来设置错误指示符,方法与设置密码不匹配的错误指示符的方法相同。 (请考虑使用UNIQUE标记MySQL表的uid列。 如果尝试在UNIQUE列中放置重复的信息,MySQL将抛出错误#1062 ( )。 编辑完成后,测试$ err的值。 PHP if ) )语句进行测试时,NULL字符串返回FALSE,因此可以方便地检查$ err是否为空。 使用PHP的“not”表达式,即感叹号。 如果有错误,测试将失败,代码将下降到第48行,此处显示错误消息,并再次显示注册表单。 如果没有阻止注册的错误,可以在第28行继续处理。 将用户ID、密码和随机数组合在一起,创建了完全唯一且不可预测的值。 这是可以在cookie上使用的“唯一的用户密钥”。 为什么只使用数据库的auto_increment键? 因为Cookie的可预测值会引起黑客攻击。 例如,如果黑客确定cookie的值为“123”,则黑客可能会尝试将cookie更改为“122”,以查看发生了什么。 唯一的数据组合md5 ) )使用散列值时,很难推测可能对黑客cookie起作用的值。 我们的查询将用户ID、密码和唯一的用户名列入表中,我们的登录完成了。 我们的客户现在可以登录了。 但是,为什么注册后要让他们分别登录呢? 第一行代码第6533行,允许您在注册时完成登录。
我们一直希望对我们的客户好! 接下来,我们将关注客户是否希望他们记住登录状态。 如果选中" rme "复选框,则会设置为$ POST数组。 可以对其进行测试,以确定是否需要记住客户端。 (与type=“ text”的空输入字段不同,未选定的type=“ checkbox”字段根本不出现在$ _POST数组中。)。 因此,如果存在" rme ",则调用Remember_me ( )函数并将其传递给唯一的用户密钥。 如果没有,则跳过此步骤,不设置cookie。 注册和登录已完成。 在行42中欢迎客户,在行44中结束脚本。 这是注册脚本:
PHP//ray _ ee _ register.PHP require _ once ( ray _ ee _ config.PHP ); //weassumenoerrorsoccurred $ err=null; //waseverythingweneedpostedtothisscriptif ( empty ( $ _ post [ ' uid ' ] ) ) (! empty($_post['pwd'] ) ) (! empty($_post['vwd'] )、wehavetheposteddata.escapeitforuseinaquery $ uid=$ mysqli-real _ escape $ pwd=$ mmd $ vwd=$ mysqli-real _ escape _ string ( $ _ post [ ' vwd ' ] ); //dothepasswordsmatchif($pwd!=$VWD($err.='
故障: chooseandverifypasswordsdonotmatch '; //doestheuidalreadyexist $ SQL=' selectuidfromee _ usertablewhereuid=' $ uid ' limit1'; if (! $RES=$mysqli-query($SQL ) ) trigger _ error ( $ mysqli-error,E_USER_ERROR ); $num=$res-num_rows; if$num$err.='
fail:uid $ uidisalreadytaken.choose another '; //iftherewerenoerrorsthatpreventregistrationif (! $ err ( (/maketheuniqueuserkey $ uuk=MD5 ) $uid.$pwd.rand ); $ SQL=' insert into ee _ usertable ( uid,pwd,uuk ) values )、( $pwd )、( $uuk ) ); if (! $RES=$mysqli-query($SQL ) ) trigger _ error ( $ mysqli-error,E_USER_ERROR ); //store the user-idinthesessionarray $ _ session [ ' uid ' ]=$ uid; //is the ' remember me ' checkboxsetif ( isset ) $_post['rme'] ) remember_me ) $uuk ); //registrationandlogincompleteecho '
welcome $ uid.registration complete.you are logged in.'; echo '
CLICK HERE TO GO TO THE HOME PAGE '; die (; //iftherewereerrorselse { echo $ err; echo '
SORRY,REGISTRATION FAILED '; }//endofformprocessing-putuptheform
客户端身份验证-现在可以在登录页面中注册用户。 另外,还有一个测试页面,可以确认实际的注册。 您需要创建登录页面和注销页面。 登录页面使用类似于注册页面的结构。 需要" configuration "页面。 然后测试是否提供了所需的凭据(第5行)。 过滤并清理外部输入(第8-9行),在查询数据库中查找UID和PWD字段(第12-20行)中完全匹配的内容。 如果在UID和PWD中找不到匹配的行,则第20行的if (语句失败,脚本下降到第46行。 您可以在此处告诉客户端验证失败,并指示登录名已重新形成。 如果找到要搜索的行,则获取该行(第23行)并将UID值复制到会话数组(第26行)以指示客户端已登录。 下一步是确认客户是否选中了“记住”框。 如果测试此复选框(第29行)并选中该复选框,则调用Remember_me )函数,并传递注册时创建的唯一用户密钥。 Remember_me ( )函数为浏览器设置长寿命cookie。 如果没有此cookie,则只使用会话cookie来记住客户端。 浏览器窗口关闭后,会话cookie也会过期。 登录过程的最后一步是确定客户端下一步要去哪里。 要执行此操作,请测试会话数组中的entry_uri。 如果是由安装脚本的access_control ( )函数设置的,则header ) )命令中可以使用此地址将客户端还原为原始页面。 如果未设置此选项,则可以改为重定向到主页。 当然,但请不要在登录脚本中添加access_control (函数。 否则,代码可能会导致服务器循环,这是一个登录脚本:
PHP//ray _ ee _ log in.PHP require _ once ( ray _ ee _ config.PHP ); //waseverythingweneedpostedtothisscriptif ( empty ( $ _ post [ ' uid ' ] ) ) (! empty($_post['pwd'] )、wehavetheposteddata.escapeitforuseinaquery $ uid=$ mysqli-real _ escape $ pwd=$ mmd //constructandexecutethequery-countthenumberofrowsreturned $ SQL=' select uid,uukfromee _ usertablewhereuid=' $ uid //IF THE QUERY FAILED,GIVE UP if (! $res ) trigger_error($mysqli-error,E_USER_ERROR ); //thereshouldbeonerowifthevalidationwasprocessedsuccessfully $ num=$ RES-num _ rows; if($num ) )/retrievetherowfromthequeryresultsset $ row=$ RES-fetch _ assoc ); //store the user-idinthesessionarray $ _ session [ ' uid ' ]=$ row [ ' uid ' ]; //is the ' remember me ' checkboxsetif ( isset ( $ _ post ( ' rme ) ) ) remember_me ) $row('uuk ); (/redirecttotheentrypageortothehomepageif ) isset ) $_session('entry_uri ' ) ) header ) ' location:) $ _ sion er }else{header('location://); 退出; }//endofsuccessfulvalidationelse { echo ' sorry,validationfailedusing $ uid and $ pwdn '; }//endofformprocessing-putuptheloginform
取消客户端身份验证-如果通过清除退出页面“记住”复选框登录客户端,则当浏览器窗口关闭或会话垃圾回收例程检测到长时间不活动时,会自动行(通常约24分钟。 但是,客户可能希望有意注销,也可能希望谨慎地在公共计算机上注销。 因此,还必须提供注销脚本,如下所示: 像往常一样,我们的第一步是加载“配置”脚本。 然后,从会话数组中收集UID或设置替代值。 此消息用于“再见”消息。 因此,即使客户端连续两次登录注销脚本,或者在客户端未登录时尝试以某种方式去那里,它也会尝试选择有意义的数据字符串。 这是在三项运算符语句(第5行)中完成的。 我们会“记住我”处理cookie (如果有的话) (第7-12行)。 下一步是清除会话数组。 第十五行。 虽然这可能看起来很无力,但您也可以考虑永久删除会话是否有意义。 如果客户端注销后会话中仍有剩馀信息,则只能在第15行取消设置$ _SESSION [“ uid”]并跳过剩馀的代码。 但是,请勿使用unset($ _ SESSION )清除数组。 请参照这里的注意事项。 http://PHP.net/manual/en/session.examples.basic.PHP最后,使用在第五行中创建的数据字符串可以说“再见”。 激活标题,而不是浏览器输出(“位置://”查看下一个“出口”; 最后一行声明。 这里并不是说得很严密,但在标题(“Location”)句子后使用“exit”是个好习惯。 为什么? 因为在发送header ( )后,脚本将继续正常运行,并且在浏览器接收到标头并重定向停止脚本之前,脚本将运行不可预测的时间。 虽然有许多适合的header ( )语句可以作为完整脚本的一部分内联,但是如果使用的语句旨在用作脚本的最后一条语句,则必须执行其他步骤以确保它实际上是要执行的最后一条语句。 这是注销脚本:
PHP//ray _ ee _ logout.PHP require _ once ( ray _ ee _ config.PHP ); //grabtheuidoraconstantforthegoodbyemessage $ uid=( isset ( $ _ session ( ' uid ' ) )、'.$_session ) ) ) isset ( $ _ cookie [ ' uuk ' ] ) setcookie('uuk ',',$cookie_expires,'/' ); //cleartheinformationfromthe $ _ session array $ _ session=array (; //IF THE SESSION IS KEPT IN COOKIE,forcesessioncookietoexpireif ( isset ( $ _ cookie [ session _ name ( ) ) ) setcookie ) //tellphptoeliminatethesessionsession _ destroy (; session_write_close (; //say goodbye . echo ' youareloggedout $ uid.goodbye.'; //orremovethegoodbyemessageandactivatetheselinestoredirecttothehomepage//header ( ' location://' ); //exit;
客户安全-在密码页面上,我们知道需要不时更改密码。 向客户提供这个功能非常简单。 与注册页一样,密码页采用了新密码对,并验证数据库是否经过了匹配更新以保存新密码。 但是有重要的区别。 每次更改数据模型的一部分时,都必须重新验证客户密码。 为什么? 因为我们是人,所以有可能不小心让计算机保持登录状态。 偷偷摸摸的人可能会试图在我们没看到的时候更改我们的密码(或其他信息)。 为了降低这种风险,我们使用的设计模式与现代ATM控制台中使用的设计模式相似。 每次提款时,都需要重新输入PIN码。 这是一个小麻烦,也是强有力的安全措施。 因此,在“更改密码”脚本中执行相同的操作。 每次更改客户记录的重要内容(如电子邮件地址和送货地址)时,都使用此设计模式。 第一步是加载" config "脚本,并调用访问控制功能以获取客户端的uid。 假设没有发生错误(第8行)。 向客户端请求三个信息:旧密码和新密码。 输入两次以确保正确输入新密码。 只要具备这三个条件(第11行),就可以开始处理请求。 清理查询中使用的值。 (行14-17 )。 接下来,测试两个密码字段是否匹配。 这是因为客户端已填写了type=“ password”的表单输入字段,浏览器在输入时会隐藏输入内容。 为了让客户满意,我输入了两次密码,并要求他们确认是否一致。 (第20行) 如果不匹配,请在$ err变量中添加错误消息。 然后检查数据库以确保UID记录与旧密码一起存在。 用户表中应该只有这样的行。 否则,将其视为错误,并使用与设置密码不匹配错误指示符相同的方法设置错误指示符。 第26行-在密码末尾的$ err变量中添加错误消息。 编辑完成后,测试$ err的值。 如果有错误,测试将失败,代码将下降到第42行,此处显示错误消息,并再次显示密码表单。 如果没有阻止更改密码的错误,可以在第32行继续处理。 请注意,第32行的UPDATE查询中的WHERE子句与第23行的SELECT查询中使用的WHERE子句完全相同。 我知道只有一行满足这个WHERE子句。 因此,我们确认了正确的行会用新密码更新。 我告诉过你,为了展示MySQL的性能,数据库被限制在一行。 这样可以避免表扫描。 如果更新了匹配行,MySQL将知道工作已完成,然后停止执行。 密码更改完毕。 向客户发送成功消息。 第6536行。 如果在实际实现中,用户表中有客户的电子邮件地址,则可以扩展该地址以发送有关密码更改的电子邮件。 使用适当的安全方法无法发送实际密码。
PHP//ray _ ee _ password.PHP require _ once ( ray _ ee _ config.PHP ); //accesstothispageiscontrolled $ uid=access _ control (; //weassumenoerrorsoccurred $ err=null; //waseverythingweneedpostedtothisscriptif ( empty ( $ _ post [ ' old ' ] ) ) (! empty($_post['pwd'] ) ) (! empty($_post['vwd'] )、wehavetheneededdata.escapeitforuseinaquery $ uid=$ mysqli-real _ escape $ old=$ Mme $ pwd=$ mysqli-real _ escape _ string ( $ _ post [ ' pwd ' ] ); $ vwd=$ mysqli-real _ escape _ string ( $ _ post [ ' vwd ' ] ); //dothepasswordsmatchif($pwd!=$VWD($err.='
故障: chooseandverifypasswordsdonotmatch '; //doestheuidandoldpasswordcombinationexist $ SQL=' selectuidfromee _ usertablewhereuid=' $ uid ' and pwd=' $ old ' lime $RES=$mysqli-query($SQL ) ) trigger _ error ( $ mysqli-error,E_USER_ERROR ); $num=$res-num_rows; if ($num!=1) $err .='
故障: $ uiddoesnothavepassword $ old '; //iftherewerenoerrorstopreventthepasswordchangeif (! $ err (//updatethetabletochangethepassword $ SQL=' update ee _ usertablesetpwd=' $ pwd ' where uid=' $ uid ' and pwd if $RES=$mysqli-query($SQL ) ) trigger _ error ( $ mysqli-error,E_USER_ERROR ); //PASSWORD CHANGE IS COMPLETE echo '
THANK YOU,$uid. PASSWORD CHANGE IS COMPLETE.'; echo '
CLICK HERE TO GO TO THE HOME PAGE '; die (; //iftherewereerrorselse { echo $ err; echo '
SORRY,PASSWORD CHANGE FAILED '; }//endofformprocessing-putuptheform
简介-实践这是使用基本PHP身份验证用密码保护网页的所有步骤。 通过这种结构,可以显示公共注册和登录页面,并通过组合公共、受保护的页面和部分受保护的页面来构建站点。 最重要的是,使用一行PHP代码进行身份验证测试。 这些脚本标识使用PHP会话登录的客户端。 客户可以让网站记住并支持他们的状态。 他们可以随时注销,也可以在一段时间内不活动后自动注销。 他们可以随时更改密码以保护自己的帐户信息。 虽然此处的注释和代码在大多数PHP安装中可以正常工作,但这只是教程的示例,您不希望在生产环境中“按原样”使用。 因此,请根据客户的特定需求自由复制和修改。 注:虽然这些了解PHP会话的脚本以合理的方式使用PHP会话,但我们发现它们很容易过度考虑PHP会话的工作方式。 比预想的简单! 您可能需要阅读这两篇文章,以更好地理解PHP客户端身份验证所依赖的基本技术。 关于PHP会话的文章。 有关HTTP客户端/服务器协议的文章。 后记:要防止自动注册,你想知道在线论坛是怎么获得这么多垃圾伟哥广告的吗? 广告由“攻击”机器人脚本放置。 这些脚本会找到注册表单,注册帐户,然后使用该帐户发布不需要的资料。 两种技术的结合可以降低这种入侵的风险。 首先是在注册表中使用CAPTCHA测试。 二是“握手”。 这需要额外的步骤以通过电子邮件说明确认注册。 这两种方法都单独有效。 总的来说,它们更有效。 后记: MySQL和MySQLI(2014年春天)这篇文章最初写于几年前,当时PHP支持MySQL数据库的扩展。 之后发生了变更。 如果您使用本文的旧版本作为指南,则可能需要修改脚本。 幸运的是,选择面向对象的MySQL i可以非常容易地完成更改。 有关PHP取消对MySQL支持的原因以及如何使脚本保持运行的信息,请参阅本文。 本文介绍了如何将过程MySQL代码转换为MySQL i或PDO。 补充: PHPsession_unregister((2014年秋季) )一些旧代码集包含使用session_unregister )函数的“注销”示例。 PHP多年前不推荐这个功能,但最近删除了。 遗憾的是,PHP代码示例没有过期日期,因此可能会遇到没有警告标签的旧代码。 如果脚本使用session_unregister ( ),则必须使用相同的函数调用参数将函数名称替换为unset ( )。 以后请勿使用session_unregister (、session_register )或session_is_registered )。 要理解本文的其馀部分,您可能想更新关于PHP会话如何工作的记忆。 注:关于保存密码,实际上不会以明文形式保存客户端密码。 PHP md5 ) )函数对密码进行编码。 MD5是“消息摘要”的缩写。 请在这里阅读评论。 如果我知道自己在做什么,并且正确使用了md5 ( ) ( md5 ) ),我不同意散列对于大多数用例来说是不够的。 但是,许多专家赞成使用密码散列。 至少是加密。 这是我对md5 )的看法。 1 .假设愚蠢地用明文保存了客户端密码。 优点:如果客户端忘记了密码,脚本可以发送客户端密码。 缺点:如果数据库被破坏,则会公开所有客户端密码。 2 .假设您没有保存明文密码,却愚蠢地保存了密码的md5 ) )摘要。 看起来是这样.5F4 DCC3b5 aa 765 d 61 d 8327 deb 882 cf 99 .这是“密码”的md5。 这个md5 ) )字符串是否与“password”一致,不能光看就很容易判断,但是md5 ) )摘要的问题是编程上是乘方。
不管散列多少次密码,总是得到相同的md5 ) )字符串。 如果两个人选择相同的密码,则md5 ) )字符串将相同。 黑客知道最受欢迎的密码md5 ) )字符串,因此数据库被破坏时会公开很多客户端密码。 黑客知道多少个普通密码? 你能相信几百万人吗? 你最好相信! 3 .如果让客户选择自己的密码,其中一个选择“密码”,黑客很可能会破解其他常用密码。 流行密码的md5 ) )匹配字符串的暴力破解方法在计算上是微不足道的。 字典中的每个单词最多需要几秒钟才能与md5 )摘要匹配。 4 .为了使解密更难,在某些子行业出现了各种各样的关于伏都教徒和密码学的无厘头。 可以避免胡说八道,从OWASP项目中了解更多信息。 可以使用密码散列来增强密码的安全性。 5.MD5 )是幂等的,因此为了安全起见,必须采取某些措施来破坏“密码”和5 F4 DCC3b5 aa 765 d 61 d 8327 deb 882 cf 99之间的直接链路。 那是在编码过程中添加到密码中的“盐”。 在密码后添加盐字符串。 幂等关系不仅需要密码,还需要盐。 因此,如果客户端选择“密码”,服务器将存储md5字符串(如“密码XYZ”),并将结果汇总到cceef 54 FDE 042 f 058 f 571084338 E2C 40。 比较这些md5字符串,以确定是否可以看到关系。 我6 .你的盐不需要轻易推测。 但是,要使PHP在脚本运行时可供程序使用,必须将其保存在某个位置。 请小心保护。 如果盐析字符串和算法被破坏,可能会暴露客户的密码。 您可能希望将其放入存储在WWW根目录之上的PHP脚本中( include ) ),并将其引入Web根目录的范围。 7 .在密码的两端可以加入盐(盐和胡椒粉)。 可以使用非常长的任意字符串来放盐和胡椒。 如果在客户端的输入密码框中添加相同的盐和胡椒粉,md5 ) )算法将创建消息摘要,例如幂。 可以使用简单的SQL查询核对密码。 8. md5 )冲突的可能性(两个不同的输入字符串匹配同一消息摘要)与DNA序列遇到别人的可能性几乎相同。 理论上是可能的,但不能赌。 9 .加盐密码有多牢固? 谁都会买啤酒。 这个md5 )创建摘要的原始输入字符串是什么? 为了便于搜索e0f 1299 ed 629 d3c 8826 e2d2be 4780 cf原始输入字符串,此处是指向md5 )算法描述的链接。 在33558 www.FAQs.org/rfcs/RFC 1321.html中,我们在服务器上安装了此易于使用的脚本。 在这里进行实验。 http://www.icono un.com/demo/MD5.PHP 10 .选择盐和胡椒粉字符串进行加密,大多数情况下可以通过MD5 )摘要保护客户端密码。 但是不能解决愚蠢的问题。 如果客户选择“密码”,并且登录过程只需要一个电子邮件地址和密码,则很少有机会保护该客户免受暴露。 内部如何编码“密码”并不重要。 任何知道站点中电子邮件地址的人都可以尝试与“密码”或其他常用密码进行配对,以验证配对是否有效。 确实,如果你的人口足够多,客户社区里有人会使用“密码”,她将成为任何攻击的最初受害者之一。 11 .出于第十个原因,某些密码选择过程可能需要使用字母和数字的组合,例如,使用大小写。 我觉得这些很讨厌,倾向于使用多字密码短语的概念。 不是密码。 肯定有流行和常用的短语。 然后,从短语中选择随机单词,包含不是单词的东西是明智的。 高盐短语至少和高盐密码一样好。
12. md5 ) )字符串始终是32个字符的十六进制数字,无论输入字符串包含什么。 因此,数据库存储的列宽必须为32字节。 ArsTechnica的这篇文章为黑客可能如何攻击编码密码提供了内部人士的意见。 最终,密码就像防火保险箱的门。 根据时间和温度进行评价。 坚固的门意味着更多的时间焚烧东西。 不幸的是,正如ArsTechnica所做的那样,所有练习都将基本密码和密码短语添加到字典中,字典攻击最早成功。 要保护的内容非常重要。 如果有保龄球得分、购买历史、医疗记录、财务细节或核发射代码,安全措施可能会有所不同。