📄 03-auth.sgml
字号:
<!-- $Id: 03-auth.sgml,v 1.1.1.1 2000/04/17 16:40:00 kk Exp $ --><sect1>Auth<p>Authentication management can be used to authenticate a session,that is, to identify the user at the client side of the session.Authentication is done inline, with HTML forms, <em/not/ withHTTP authentication (that's the browser popup you get when youhit a page protected with htaccess). Inline authentication hasseveral advantages over HTTP authentication:<itemize><item>It can be undone: A session can be un-authenticated, theuser can "log out".<item>It can expire: A session can automatically beun-authenticated after a given idle time.<item>It can be customized: You are not limited to user/passwordpairs. Instead you could use a customer number, operator idand a password to log in. Also, you have full control overthe login screen, which is a normal HTML page with logos,help and forms as you see fit.<item>It is database based. Authentication is being done againsta database of your design, not a htpasswd text file.<item>It is per page. You decide on a per-page basis which pagesare authenticated and which aren't.<item>It can be user authenticating and optionally selfregistering. In <em/registration/ mode, a user without a valid login isencouraged to register and an account is created for thisuser.<item>It works with CGI PHP. HTTP authentication is availableonly in mod_php.<item>It is integrated with a permission checking scheme.</itemize><sect2>Instance variables<p><table><tabular ca="">classname<colsep>Serialization helper: The name of this class.<rowsep>persistent_slots<colsep>Serialization helper: The names of all persistent slots.<rowsep>lifetime<colsep>Maximum allowed idle time before the authentication expires. If set to 0, The authentication never expires (as long as the session remains active).<rowsep>refresh<colsep>Maximum allowed time before the authentication info (perms and alike) are re-read from the database calling <tt/auth_refreshlogin()/ method. If set to 0 authentication info are read only at the login stage.<rowsep>mode<colsep>Authentication mode: <tt/log/ or <tt/reg/ (see below).<rowsep>database_class<colsep>A classname. Auth uses this class to make a database connection.<rowsep>database_table<colsep>Database table used to keep the session variables.<rowsep>magic<colsep>An arbitrary value used in uniqid generation.<rowsep>nobody<colsep>Flag: If true, we use default authentication.<rowsep>cancel_login<colsep>The name of a button that can be used to cancel a login form<rowsep></tabular><caption>Accessible instance variables.</caption></table><table><tabular ca="">db<colsep>Internal: The database connection object instance.<rowsep>auth<colsep>Internal: User authentication information, see below.<rowsep>in<colsep>Internal: Used in default authentication mode.<rowsep></tabular><caption>Internal instance variables.</caption></table><sect2>Instance methods<p><sect3>Accessible instance methods<p><descrip><tag>url()</tag><p> A function that can be used in <tt/auth_loginform()/a and <tt/auth_registerform/. It returns the appropriate "action=" attribute to the form tag.<tag>purl()</tag><p> A function that can be used in <tt/auth_loginform()/a and <tt/auth_registerform/. It prints the appropriate "action=" attribute to the form tag.<tag>login_if($t)</tag><p> A function that can be used to change the current user identity. See the section and example on using default authentication below.<tag>unauth($nobody = false)</tag><p> This function destroys the authentication information in <tt/$this->auth/, forcing the user to relogin the next time a protected page is being loaded. <tt/$this->auth["uname"]/ is being kept, so that the correct username is available as a default. Since V6: To give the user the credentials of `nobody', pass true as the first parameter to unauth. This will also change <tt/$this->auth["uname"]/. Since V7.2: Passing $nobody to this method is deprecated.<tag>logout($nobody = $this->nobody)</tag><p> This function destroy all authentication information in <tt/$this->auth/, forcing the user to relogin the next time a protected page is being loaded. Most applications want to use <tt/$this->unauth()/ instead. Since V6: To give the user the credentials of `nobody', pass true as the first parameter to logout. This defaults to the value you set in the class definition (<tt/$nobody/). <tt/logout()/ will call <tt/unauth()/ (passing <tt/$nobody/), so the behaviour is identical (except <tt/logout()/ will always clear <tt/$this->auth["uname"]/ and unregister the auth class). Since V7.2: Passing $nobody to this method is deprecated.<tag>is_authenticated()</tag><p> Will return false, if the current authentication is invalid or expired. Will return the authenticated uid otherwise.<tag>auth_preauth()</tag><p> This function can be overridden in a subclass to Auth. It is being called as the very first step in the authentication process and has the opportunity to authenticate the user without a loginform being displayed (by deriving all necessary information telepathically, or by using cookies, or divining the user identities from the incestines of a dead squirrel).<p> If it returns a UID value, the user is authenticated and neither auth_loginform() nor auth_validatelogin() are called. If it returns false, all goes on as usual.<tag>auth_loginform()</tag><p> This function must be overridden by a subclass to Auth. It should output HTML that creates a login screen for the user. We recommend that you use an <tt/include()/ statement to include your HTML file.<tag>auth_validatelogin()</tag> This function is called when the user submits the login form created by <tt/auth_loginform()/. It must validate the user input. If the user authenticated successfully, it must set up several fields within the <tt/$auth[]/ instance variable: <descrip> <tag>"uid"</tag><p>must contain the user id associated with that user. <tag>"uname"</tag><p>must contain the user name as entered by the user. <tag>"exp"</tag><p>must not be tampered with (field is maintained by <tt/start()/, contains the time when the login expires). <tag>"perm"</tag>if you want to use the permission feature, you must store the permissions of the validated user here. (Hint: due to a name conflict with sybase, "perm" is called "perms" in all the databases tables. Look for this small difference!) </descrip> See the example below for more information.<tag>auth_refreshlogin()</tag> This function is called every <tt/refresh/ minutes. It must refresh the authentication informations stored in <tt/auth/ array by <tt/auth_validatelogin()/ method. It is not called if the user is logged in as nobody. It must return true on success, false otherwise (i.e.: the userid is no longer valid).<tag>auth_registerform()</tag><p>See auth_doregister().<tag>auth_doregister()</tag><p>These functions mirror <tt/auth_loginform()/ and <tt/auth_validatelogin()/ in registration mode.</descrip><sect3>Internal instance methods<p><descrip><tag>start()</tag><p> Initialization function, does the authentication. If we are in <tt/log/ (login) mode, <tt/auth_loginform()/ is called to draw a login screen. When the login screen is submitted back, <tt/auth_validatelogin()/ is called to validate the login. If the validation was successful, the actual page content is shown, otherwise we're back at <tt/auth_loginform()/. In <tt/reg/ mode, <tt/auth_registerform()/ is called to draw a registration form. When the registration form is submitted back, <tt/auth_doregister()/ is called to register the user and to validate the session. If registration was successful, the actual page content is shown, otherwise we're back at <tt/auth_registerform()/.</descrip> <sect2>Example<p>Use a subclass of <tt/Auth/ to provide parameters for yourauthentication class and to implement your own <tt/auth_*/ functions.<tscreen><code>class My_Auth extends Auth { var $classname = "My_Auth"; # Object serialization support var $lifetime = 15; ## DB_Sql subclass and database table to use var $database_class = "DB_Session"; var $database_table = "auth_user"; ## Some magic value to make our uids harder to guess. var $magic = "Abracadabra"; ## Use an own login form function auth_loginform() { global $sess; include("loginform.ihtml"); } function auth_validatelogin() { global $username, $password; ## form variables from loginform.ihtml ## If authentication fails, loginform.html will ## find $this->auth["uname"] set and use it. $this->auth["uname"]=$username; ## Value to return in case auth fails. $uid = false; ## Check the database for this user and password pair. $query = sprintf( "select * from %s where username = '%s' and password = '%s'", $this->database_table, addslashes($username), addslashes($password) ); $this->db->query($query); ## If we found a matching user, grab the uid and permissions... while($this->db->next_record()) { ## Required. $uid = $this->db->f("uid"); ## Optional, for the perm feature. $this->auth["perm"] = $this->db->f("perms"); ## if you use perm feature be aware, that the db-field in our ## example table is called "perms" due to a name conflict with sybase } return $uid; }}</code></tscreen>Your <tt/loginform.ihtml/ contains HTML and PHP code to draw a loginform. <tt/$this->auth["uname"]/ will be empty on the first loginattempt and set on all further login attempts. You can use thisto detect repeated login attempts and display an appropriateerror message. You must print the result of <tt/$this->url()/ tocreate your forms action attribute.See the provided <tt/loginform.ihtml/ for an example.Use the page management functions (see above) to use yourauthentication subclass. The feature name for authenticationmanagement is <tt/auth/; provide the name of your <tt/Auth/ subclass asa parameter to the <tt/auth/ feature. The <tt/auth/ feature requires the<tt/sess/ feature:<tscreen><code> page_open(array("sess" => "My_Session", "auth" => "My_Auth"));</code></tscreen><sect2>Using default authentication<p> Many applications want to use <tt/$auth/ and <tt/$perm/ objects to protect functionality on a page, but do want to make the unprotected part of this page available to users with no account. This presents a kind of dilemma, because you need <tt/$auth/ and <tt/$perm/ objects to protect functionality on a page, but you don't want a login screen to appear by default. Default authentication solves this dilemma by providing a special uid and uname "nobody", which is guaranteed to fail every permission check. If you set the <tt/nobody/ flag, <tt/$auth/ will not create a login screen to force a user to authenticate, but will authenticate the user silently as <tt/nobody/. The application must offer a login button or other facility for users with accounts to change from that id to their real user id.To use default authentication, create a subclass of <tt/My_Auth/as shown above with the <tt/nobody/ flag set (<em/Note:/ No needto extend in two steps. The only important thing here is thatthe <tt/nobody/ flag is set.)<tscreen><code>class My_Default_Auth extends My_Auth { var $classname = "My_Default_Auth"; var $nobody = true;}</code></tscreen>To create a page that uses default authentication, use the pagemanagement functions. Check for relogin requests with the<tt/login_if()/ function. Create a relogin link on your page.<tscreen><code><?php // using Default Authentication page_open(array("sess" => "My_Session", "auth" => "My_Default_Auth")); $auth->login_if($again); if ($auth->auth["uid"] == "nobody"):?> <A HREF="<?php $sess->purl("$PHP_SELF?again=yes") ?>">Relogin</A> to this page.<?php endif ?></code></tscreen><sect2>Using Challenge-Response Authentication<p> As distributed, <tt/local.inc/ contains an example class named <tt/Example_Challenge_Auth/, which uses a Challenge-Response authentication scheme. If the client browser supports Javascript, this login screen does not transmit passwords in clear over the network. If the client does not support Javascript, login is still possible, but passwords are transmitted in clear, as regular <tt/Example_Auth/ always does. <tt/Example_Challenge_Auth/ is there to demonstrate advanced usage of PHP and Javascript and to show off the flexibility of the library base classes: The Challenge-Response authentication scheme has been implemented completely and naturally in local.inc by subclassing <tt/Auth/ with no alteration of library code. <tt/Example_Challenge_Auth/ includes <tt/crloginform.ihtml/. It also requires that the file <tt/md5.js/ is present in the document root directory of your web server. That file contains an implementation of the MD5 message digest algorithm done by Henri Torgemane. The basic idea behind this authentication scheme is simple: <tt/$auth->auth_loginform()/ creates a challenge value which is incorporated into this form. When the user tries to submit the form, MD5("username:password:challenge") is calculated and filled into the reply field. The password field is erased. The server can calculate the expected reply from the username received, the password in the database and the challenge, which it knows. It can compare the expected reply to the actual reply value. If they match, the user is authenticated. If the reply field is empty and password is set, the server knows that the client cannot do Javascript. The user can still be authenticated, but the password is visible on the network.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -