⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 03-auth.sgml

📁 PHPLOB注释详细版 使用模板技术的好帮手 PHP最有用的东东了
💻 SGML
📖 第 1 页 / 共 2 页
字号:
   The class is a dropin-replacement for <tt/Example&lowbar;Auth/.<sect2>The complete guide to authentication and user variables<p>This feature has originally been written for the PHPLIB mailinglist by Kristian K鰄ntopp and was included into thedocumentation later.<sect3>How is the <tt/Auth/ class used usually?<p>Usually, you write code like this into the top of the page youwant to protect:<tscreen><code><?phppage&lowbar;open(array(    "sess" =&gt; "My&lowbar;Session",     "auth" =&gt; "My&lowbar;Auth"));?&gt;&lt;!-- your code here --&gt;&lt;?phppage&lowbar;close()?&gt;</code></tscreen><sect3>How does <tt/$auth/ work internally?<p>When you access this page, the call <tt/to page&lowbar;open()/ is beingmade as the first thing on that page. <tt/page&lowbar;open()/ createsan instance of <tt/My&lowbar;Auth/ named <tt/$auth/ and starts it.<tt/$auth/ then detects that you are not authenticated (how itdoes, I will explain below) and displays <tt/loginform.ihtml/.$auth then exits the interpreter, so that &lt;!-- your code here--&gt; is never being executed or displayed.The user now sits in front of a <tt/loginform.ihtml/ screen,which is shown under the URL of the page the user originallytried to access. The loginform has an action URL, which justpoints back to itself.When the user filled out the loginform and submits it, the verysame URL is requested and the above <tt/page&lowbar;open()/ isreexecuted, but this time a username and a password aresubmitted. When the <tt/$auth/ object is created and started, itdetects these parameters and validates them, resulting in eithera NULL value or a valid user id. If the validation failed,creating an empty user id, the loginform is displayed again andthe interpreter exits. Again &lt;!-- your code here --&gt; is notexecuted.If a UID is returned, that UID and a timestamp are being madepersistent in that session and <tt/$auth/ returns control to<tt/page&lowbar;open()/. When <tt/page&lowbar;open()/ finishes, which it mayor may not do, depending on the presence and result of anoptional <tt/$perm/ check, &lt;!-- your code here --&gt; is beingexecuted or shown.Later calls to other pages or the same page check for thepresence of the UID and the timestamp in the sessions data. Ifthe UID is present and the timestamp is still valid, the UID isretained and the timestamp is refreshed. On <tt/page&lowbar;close()/both are written back to the user database (Note: Authenticatedpages REQUIRE that you <tt/page&lowbar;close()/ them, even when youaccess them read-only or the timestamp will not be refreshed).If the UID is not present (<tt/$auth-&gt;logout()/ or<tt/$auth-&gt;unauth()/ have been called, for example) or thetimestamp has expired, <tt/$auth/ will again intercept pagedisplay and draw the loginform.The only way to get into a page with an <tt/$auth/ object on itis to have a UID and a valid timestamp in your session data(Note: This is true even for default authentication. Thesecreate a dummy UID and timestamp in your session data).<sect3>How do $sess and $auth interact?<p>Your browser has a session cookie, named after your sessionclass. This is the only thing that is ever shipped between yourbrowser and PHPLIB, as far as core functionality is concerned.The session cookie value is used as a reference into<tt/active&lowbar;sessions/, to retrieve PHPLIB generated PHP code,which is then <tt/eval()/ed and recreates your session variableswithin <tt/page&lowbar;open()/.Part of the <tt/$auth/ object now makes itself persistent and isretrieved when the <tt/$sess/ part of <tt/page&lowbar;open()/ is beingexecuted. This is just before the <tt/$auth/ part of<tt/page&lowbar;open()/ gets its turn, so that <tt/$auth/ can rely on itspersistent data being present when it is being called.From the PHPLIB source you all know that <tt/$auth/ has only onepersistent slot, called <tt/$auth-&gt;auth[]/, of type hash. Thishash contains the slots <tt/uid/, <tt/exp/ and <tt/uname/.<tt/$auth-&gt;auth["uid"]/ is the currently authenticated user id,<tt/$auth-&gt;auth["exp"]/ is the currently active expirationtimestamp (Unix time&lowbar;t format) for that uid.<tt/$auth-&gt;auth["uname"]/ is completely irrelevant as far as theregular PHPLIB <tt/Auth/ class is concerned. It is relevant inthe context of the supplied default <tt/Auth/ subclass<tt/Example&lowbar;Auth/, though.So a session is authenticated, if it contains <tt/$auth-&gt;auth["uid"] !=false/ and <tt/time() < $auth-&gt;auth["exp"]/.<sect3>Where is the beef?<p>The original <tt/Auth/ class as included in PHPLIB makes noassumptions at all on how a loginform looks or how and whereuids come from. There is no code at all in <tt/Auth/ that everchecks anything but the above two conditions. It is yourresponsibility to modifiy a subclass of Auth in a way that theseconditions can ever be met.Auth helps you in doing this by calling its own function<tt/$auth-&gt;auth&lowbar;loginform()/ when it wants to draw a loginform.Unfortunately this function is empty in Auth itself, so you haveto provide an implementation for that. The suggested standardimplementation in <tt/local.inc/s <tt/Auth/ subclass<tt/Example&lowbar;Auth/ is<tscreen><code>function auth&lowbar;loginform() {  include("loginform.ihtml");}</code></tscreen>and you put your code into that file. We also provide samplecode for that file, but you are not limited to that code and maywrite a <tt/loginform.ihtml/ as it meets your needs.When the loginform has been filled in and submitted back by theuser, <tt/Auth/ calls <tt/$auth-&gt;auth&lowbar;validatelogin()/. Again,this function is empty in <tt/Auth/ itself and so <tt/Auth/ byitself will never function correctly. You have to subclass<tt/Auth/ and provide your own implementation of<tt/$auth-&gt;auth&lowbar;validatelogin()/ in <tt/local.inc/ to make itwork.What you actually do in that function is completely irrelevantto <tt/Auth/ itself. It only exspects that you either returnfalse, if the user-supplied authentication data was invalid, ora user id, if the user could be validated. <tt/Auth/ then takescare to create the appropriate entries (<tt/$auth-&gt;auth["uid"]/and <tt/$auth-&gt;auth["exp"]/) in the session record.<sect3>I still do not understand! What am I supposed to code?<p>You write your code into <tt/local.inc/, after you have removedthe classes <tt/Example&lowbar;Auth/, <tt/Example&lowbar;Default&lowbar;Auth/ and<tt/Example&lowbar;Challenge&lowbar;Auth/ from that file (keep a copy around, justfor reference).You code a class called <tt/My&lowbar;Auth/ and you use that name laterin your calls to <tt/page&lowbar;open/ as an argument to the <tt/auth/feature, as show at the start of this message. Follow thestandard rules for deriving persistent classes in PHPLIB whenyou create your code, that is, do it like this:<tscreen><code>class My&lowbar;Auth extends Auth {var $classname = "My&lowbar;Auth";// we inherit $persistent&lowbar;slots and do not need to modify it.// later code is inserted here}</code></tscreen>Now configure the lifetime of the authentication, that is, howmany minutes in the future shall the current value of<tt/$auth-&gt;auth["exp"]/ be? Also, name a database connectorclass and name the table that you will be using to checkusernames and passwords.<tscreen><code>  // insert this code as indicated above.  var $lifetime = 15;  var $database&lowbar;class = "DB&lowbar;Example";  var $database&lowbar;table = "my&lowbar;special&lowbar;user&lowbar;table";  // later code is inserted here</code></tscreen>Okay, now we have a basic implementation of <tt/My&lowbar;Auth/that is only lacking the required functions<tt/auth&lowbar;loginform()/ and<tt/auth&lowbar;validatelogin()/. Our implementation of<tt/auth&lowbar;loginform()/ will have access to all <tt/$sess/variables by globaling <tt/$sess/ into our context (becausethese can come in handy) and to all <tt/$auth/ variables (via<tt/$this/).<tscreen><code>function auth&lowbar;loginform() {  global $sess;  include("loginform.ihtml");}</code></tscreen>The loginform is free to do whatever it damn well pleases tocreate a form for the user to supply the needed values forauthentication. It has access to anything <tt/$sess/ andanything <tt/$this/ related.The loginform will display some input fields for the user, forexample a given name, a surname and a password. When the form issubmitted back, <tt/auth&lowbar;validatelogin()/ is being called. Theform values are global variables (or <tt/$HTTP&lowbar;x&lowbar;VARS[]/) andmust be imported into <tt/$auth-&gt;auth&lowbar;validatelogin()/. Then,<tt/$auth-&gt;auth&lowbar;validatelogin()/ is free to do whatever it mustdo to produce a unique identifier for that user (or returnfalse).Suppose you created input fields named given&lowbar;name, surname andpassword. So go ahead, global <tt/$given&lowbar;name/, <tt/$surname/and <tt/$password/ and set <tt/$uid/ to false. Then create theSQL needed to access you user table and retrieve the user recordfrom your database as indicated by <tt/$given&lowbar;name/ and<tt/$surname/ and <tt/$password/.The query may succeed, if a record with matching<tt/$given&lowbar;name/, <tt/$surname/ and <tt/$password/ is present.In that case return the uid, which uniquely identifies exactlythat (given&lowbar;name, surname) pair. Else return false.In code:<tscreen><code>function auth&lowbar;validatelogin() {  // import authentication data  global $given&lowbar;name, $surname, $password;  $uid = false;  $query = sprintf("select uid                      from %s                     where given&lowbar;name = '%s'                       and surname = '%s'                       and password = '%s'",             $this-&gt;database&lowbar;table,             $given&lowbar;name, $surname, $password);  // we really should use addslashes() here,  // or have magic&lowbar;quotes active.  // $auth-&gt;db is our DB&lowbar;Example database connection  $this-&gt;db-&gt;query($query);  // now check for any results  while($this-&gt;db-&gt;next&lowbar;record()) {    $uid = $this-&gt;db-&gt;f("uid");  }  // either $uid is false now (no results)  // or set to the last retrieved value from the uid  // column.  // Anyway we are set now and can return control  return $uid;}</code></tscreen>Okay, that's all and useable now. There is room for someimprovements, though: First we did not retrieve permission data,so this will not work, if we want to use the perm feature aswell.This is easily changed: Modify the query to <tt/select uid,perms/ instead of <tt/select uid/ alone. Of course, you may callyour perm column whatever you like, just adapt the SQLaccordingly. Also, add a line after the<tt/$uid/ assignment so that the code looks like this:<tscreen><code>  $uid = $this-&gt;db-&gt;f("uid");  $this-&gt;auth["perm"] = $this-&gt;db-&gt;f("perms");</code></tscreen>This will store the retrived <tt/perms/ value under the key<tt/perm/ within the <tt/$auth-&gt;auth[]/ array. It will be keptaround in that place in case <tt/$perm/ is called and startslooking for the current permissions of that user.Another possible improvement becomes apparent when you try tologin and fail to do so correctly: <tt/auth&lowbar;validatelogin()/returns false and you hit the loginform again. Empty loginformthat is, because we did not remember what you typed into the<tt/given&lowbar;name/ and <tt/surname/ fields before. If we rememberedwhat you typed, we could easily supply these values back to youso that you can correct them. We would also be able to detect ifthis is a second, third, ... attempt to login and display anappropriate error message somewhere in that loginform to informthe user of his or her typo. A convenient place to store thesevalues is the <tt/$auth-&gt;auth/ array, which is persistentanyway. Standard <tt/Example&lowbar;Auth/ uses the field <tt/$auth-&gt;auth["uname"]/to store that value, but you may use any field and as manyfields as you like as long as you make sure not to clash withany of the three officially used fields, <tt/uid/, <tt/exp/, and<tt/perm/.Do not try to turn the global variables <tt/$given&lowbar;name/ and<tt/$surname/ into persistent variables by calling<tt/$sess-&gt;register("given&lowbar;name")/ and<tt/$sess-&gt;register("surname")/! Remember: These are formvariables! Never ever make form variables persistent and neverever trust unvalidated user supplied from the Internet!So add the folling code just below the "global" line:<tscreen><code>  $this-&gt;auth["gname"] = $given&lowbar;name;  $this-&gt;auth["sname"] = $surname;</code></tscreen>and check for these two variables in loginform.ihtml at theappropriate places.<sect3>Ok, I did that and it works. I even understood it. Now, what exactly is that uid used for?<p>It is simply a token to indicate that the user is authenticated.We use a different token for each user, so that we can decidewhich user we are currently dealing with. You can think of theuid as a primary key for your <tt/auth&lowbar;user/ table (or whateverit is being called in your current application). The (given&lowbar;name, surname ) tuple would also be a possible primarykey, albeit a compound one. It is the external, human-readable(and probably sometimes very long) representation of theinternal uid. The password field is functionally dependent oneither of both key candidates.The internal user id should never be presented to the user; the (given&lowbar;name, surname ) pair is much more natural to handle for the userand easier to remember (A user who does not remember his or her namewould probably not be in a state of mind to operate the rest of theapplication anyway :-).The internal user id should always be used to identify a userinternally within an application, though. That is, because theuid is of a fixed length and has a known form and structure, soyou can make assumptions. A given&lowbar;name or surname may be of anylength and may contain about any character, so you probably donot want to use this as a user-reference internally.<sect3>But is the uid used internally by PHPLIB?<p>Yes, if you make use of the <tt/user/ feature of<tt/page&lowbar;open()/, that is, if you create user variables.The <tt/User/ class is actually a subclass of <tt/Session/. Thatis, user variables are just like session variables. They areeven stored in <tt/active&lowbar;sessions/. The only difference is thatthe session has a different name (it is called <tt/Example&lowbar;User/instead of <tt/Example&lowbar;Session/, if you use the classes and namessupplied in <tt/local.inc/).And in <tt/Example&lowbar;User/, the user id of the authenticated userbecomes the session id in the <tt/active&lowbar;sessions/ table. Thatis the reason why we recommend <tt/md5(uniqid("abracadabra"))/style uids.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -