Developer: PHP
Database-Based Authentication for PHP Apps, Part
1 by Michael McLaughlin
Learn how to secure
PHP-based Web applications via database-based
authentication.
Published May 2007
Managing secure access to Web pages and applications
is a common problem. You want to enable those you trust
to access data while preventing unauthorized ones from
gaining access to it. In most cases, database-based
authentication is the solution.
Authentication systems contain an Access Control List
(ACL) that lists your user credentials and matches them
to your assigned system privileges. Credentials are
typically a user name and password pair. Credentials
link your users to system privileges. System privileges
let your accounts access or modify data, and enable your
accounts to execute subsystems or subroutines. Your
accounts can be users, groups, or systems.
In this article, you will learn how to implement this
concept in PHP-based Web applications. You will learn
how to design and implement an authentication database
model, and plan and manage all aspects of user
interactions in a browser-hosted application.
In Part
2 of this article, you will explore different
methods of database access and how authentication
systems can leverage security policies in an Oracle
Virtual Private Database (VPD), as well as with the
built-in DBMS_APPLICATION_INFO package.
Architecture, Authentication, and Encryption
Architecture. When Web applications
request information from the Apache HTTP server, they
send information from the client to the server. Users
view this process as submitting a URL and receiving a
Web page in reply. A URL is only the exposed part of the
URI; the URI contains HTTP headers, cookies, and a URL.
The information is transmitted as an encoded name and
value pair in the URI.
Cookies are small text files containing clear or
encrypted text. Cookies contain the current transaction
state of communication between the browser and server
application. The content of cookies was once frequently
attached to the URI to help maintain transaction state.
A single session cookie now sends a numeric reference
that enables the prior name and value cookie pairs to be
stored securely on the server. The numeric reference is
known as a Web session ID.
When using Web application sessions, the session ID
and expiration information about the session are sent as
a special session cookie. When client browsers disallow
cookies, Web applications may default to URL rewriting,
which redirects the session cookie from the undisclosed
URI to the disclosed URL. You recognize two benefits by
leaving the data on the server and storing it by a
unique session ID — you minimize the size of the URL,
and you secure the internal details of user
interactions.
Sample Code Manifest |
Program
Name |
Language |
Description |
AddDbUser.php |
PHP |
Program file that authenticates new users and
returning active sessions; and renders a form to
enter new users into an ACL. |
create_identity_db1.sql |
SQL |
Script that builds the database and seeds
necessary rows to initialize the Web
application |
Credentials1.inc |
PHP |
Include file that defines the three global
constants you use in all oci_connect() function
calls |
SignOnDB.php |
PHP |
Program file that esets the PHP session ID
before calling the AddDbUser.php program |
SignOnRealm.php |
PHP |
Program file that authenticates credentials
and then renders the authentication values to a
static Web page |
Although keeping session information on the server is
more secure, you must guard against session hijacking. A
malicious user can hijack a session by (a) stealing a
session cookie, (b) copying a URL that includes the
session ID or (c) snatching it through a
man-in-the-middle attack. Modern browsers make this more
difficult, and PHP does not write the physical session
cookies to a file system.
A benefit of the cookie and session architecture is
that you can mine historical session data, provided you
store data in a normalized data model. The data let you
discover how customers use your Web applications. The
data also let you discover customer browsing patterns
and purchasing trends. This type of information enables
businesses to target marketing to individuals as opposed
to groups.
Authentication. You will use one of
two authentication models to verify users in your Web
applications. Your choice is between the basic
HTTP/HTTPS authentication, and the cookie and session
authentication models. A third authentication model, a
digest HTTP authentication, is under development but
appears likely to remain an incomplete solution for a
few more years.
Both of the first two authentication models let you
take credentials from a Web page and validate them
against an ACL. They also let you work successfully
whether or not the browser accepts cookies. The basic
HTTP/HTTPS and digest HTTP methods validate against a
realm without using a cookie, while the session
management writes at least a session ID cookie.
URL rewriting presents some security risks when you
send the session ID as part of the URL because some
users instant message the URL to someone else. That
other person may hijack the authorization to access or
compromise confidential data. An alternative to URL
rewriting is placing the session ID into the rendered
Web page as a hidden field. While this does create
vulnerability, it is less risky than appending the
session to the URL.
Your PHP authentication script takes a name and value
pair for the user name and password. The script then
compares the pair against data stored in your ACL. This
is the same process in either the discussed
authentication models. While it is customary to store
server-side passwords in encrypted forms, you should
recognize that any compromise of the clear text user and
password values compromises your system security.
Therefore, you should not force users to create
complex passwords because they aren't easily remembered.
Users write hard-to-remember passwords on notepads or
yellow sticky pads. Written passwords are security risks
to your Web application because hackers might find and
misuse them.
Encryption. Encryption is always a
hot topic in Web application development, deployment,
and management.
There are two encryption techniques in PHP Web
applications. The first involves encrypting your
protocol. Encrypted protocols, like HTTPS, protect you
from man-in-the-middle attacks using network analyzers,
commonly known as packet sniffers. The second involves
encrypting your user password from exposure to prying
eyes on the server.
Password encryption protects your system from attacks
best when the encrypted passwords are stored separately
from the source code. When the ACL is a file on the file
system, both the method of encryption and encrypted
values can be compromised by a single server hack. You
reduce the risk of compromising the encrypted passwords
by storing your ACL in a database.
Identity Management Data Modeling
Building an identity management data model can vary
from the simple to the complex. The simplest model is a
single table containing the ACL for your application.
Unfortunately, this model only works with basic
HTTP/HTTPS authentication.
The simplest way to implement cookie and session
authentication requires at least two tables. One table
contains the ACL, and the other contains the session
data. The following depicts a basic model:

Figure
1 Basic authentication data model
A more effective solution for authentication would
support capturing and mining user interactions. These
vary from the list of Web pages called to individual
events, like mouse clicks. Figure 2 shows a data model
that can capture user navigation and both successful and
unsuccessful logins. For our example, this data model is
created by the create_identity_db.sql script (see sample
code zip).

Figure
2 Detailed authentication data model
The larger model lets you track versions of defined
modules against runtime calls to modules. Actual
parameters map to catalog items, like books on
Amazon.com. An access log is added to track multiple
connections made during a single session. The full
details of how you implement your model can vary based
on your goals. Figure 2 also shows an example model that
supports version control in a catalog ordering
application. At present, the sample code only captures
invalid log in attempts and the ACCESS_LOG table is
renamed to reflect that difference as INVALID_SESSION
table.
Authentication Process Models
Basic HTTP/HTTPS authentication operates by
establishing a browser's credentials in a realm.
Browsers can concurrently support many realms. Realms
are set in the header of XHTML documents. They can be
manually coded in the form, or set in the AuthName
directive of the httpd.conf file. Realms act as guards
over protected server areas, and they can apply to one
or more protected server areas. One advantage of basic
HTTP/HTTPS authentication is that you don't have to code
a login or logout facility. Browsers provide the login
forms and you logout by closing all open browser
windows.
A major downfall of the basic HTTP/HTTPS
authentication method is you must close all browser
windows to end active realm authorizations. This means
that a user can authenticate, walk away from the
terminal while leaving an open browser, and enable
someone to compromise their confidential data by
hijacking their identity.
Cookie and session authentication operates by
checking user credentials against your ACL. When the ACL
is stored in a file, this means reading the file and
comparing the name value pairs of a user name and
password against a submitted clear text user name and
encrypted password.
When the ACL is stored in a database, this means one
thing on initial login and another on subsequent
connections. On initial login, you connect to the
database, read the user name and encrypted password
values from a database table; and compare the results
against the submitted clear text user name and encrypted
password. On subsequent Web requests, you connect to the
database, read the session ID, and compare results
against the submitted session ID. Unlike basic
HTTP/HTTPS authentication, you can successfully logout
while leaving the Web browser open.
While the session ID becomes a potential security
risk because of session hijacking, some reasonable
precautions can minimize this risk. The biggest security
gap can be closed by implementing your login page as a
PHP script instead of a simple text XHTML form. The
sample cookie and session code demonstrates this
approach. It ensures that a second user on a shared
machine doesn't gain entry from the prior credentials.
The implementation details are found in the following
Cookie and Session Authentication Model section.
Basic HTTP/HTTPS Authentication Model.
The basic HTTP/HTTPS authentication model
authorizes once for a realm and revokes the realm
authentication only when all browser windows are closed.
The activity diagram representing the model from within
the browser context is shown in Figure 3. Microsoft
Internet Explorer provides three attempts before failing
authentication but you can simply refresh the page to
get another three successive attempts. The Firefox
browser differs by prompting until the user cancels the
authentication process.

Figure
3 Basic HTTP/HTTPS authentication activity
diagram
You start a Web application session by entering a URL
for the login form, which then posts to the server and
sends a message back to the browser requesting that it
collect and send for validation the user's credentials.
When you submit the credentials to the SignOnDB.php
program, the code attempts to validate your log
credentials. When it works you can then use any Web
pages in the realm. Authentication failure re-prompts
with the browser login form as noted previously.
When implementing basic HTTP/HTTPS authentication,
PHP uses three predefined variable names in the $_SERVER
array. Basic HTTP/HTTPS authentication puts the user ID
and the password in the $_SERVER['PHP_AUTH_USER'] and
$_SERVER['PHP_AUTH_PW'] respectively. When the third,
HTTP_AUTHORIZATION, is not set, you submit these two
$_SERVER values to your authentication function. After
your server-side program authenticates the user,
subsequent reads of the $_SERVER array
HTTP_AUTHORIZATION name let the browser access to the
realm until it is closed.
An easy way to protect your pages in the basic
HTTP/HTTPS authentication model is to include a Boolean
control variable that is false until authentication is
verified. You display content only when the Boolean
control variable becomes true. Your code should check
for authentication, and prompt for credentials when you
are not authenticated in the realm. This code should
be found in all pages on your secure Web site.
You trigger HTTP header validation in your
server-side script by checking the values of these
predefined $_SERVER variables. The request to the
SignOnRealm.php page places these values in the returned
header, which instructs the browser to prompt with a
credential entry dialog box. Clicking the credentials OK
button sends a new request to the server-side script.
The server-side script then attempts to validate the
submitted credentials unless a user cancels the process.
These realm sign in scripts typically return a failure
message when the user cancels the process. Some sites
also shut user accounts when there are three or four
consecutive authentication failures because someone may
be attempting to hack into the system through a known
user name.
Setup Test Application. The
demonstration application uses an Oracle schema named
IDMGMT1, and the password is the same as the schema. You
can create the user and environment by following these
steps:
1. Log into the database as the privileged SYSTEM
user and run the following commands: SQL> CREATE USER IDMGMT1 IDENTIFIED BY IDMGMT1;
SQL> GRANT CONNECT, RESOURCE TO IDMGMT1;
2. Connect to the new user schema: SQL> CONNECT IDMGMT1/IDMGMT1@XE
3. Run the create_identity_db1.sql script in the
IDMGMT1 schema to create all necessary objects and seed
the SYSTEM_USER table: SQL> @create_identity_db1.sql
4. Place the following files in your htdocs directory
or a subdirectory of the htdocs directory: • SignOnRealm.php
• SignOnDB.php
• AddDbUser.php
These steps complete the setup required for our
purposes here. You can now experiment with either the
realm or session identification management examples.
Experiment with Basic HTTP/HTTPS
Authentication. You can experiment with the
realm identity management by following these steps:
1. Open the realm identification management examples
by using the following URL: http://localhost/SignOnRealm.php
2. You can use either of the following seeded
accounts as valid credentials using Basic HTTP/HTTPS
authentication. Make sure you don't have the cap lock
enabled because they are case sensitive.
User
Name |
Password |
administrator |
welcome |
guest |
guest |

Figure
4 Basic HTTP/HTTPS authentication dialog
box
After you successfully enter your credentials you
will be presented with the following page that echoes
back the plain text credentials and encrypted
password:

Figure
5 Basic HTTP/HTTPS credential validation
acknowledgment
Analyze the Basic HTTP/HTTPS Authentication
Code. After you enter your user name and
password, your script will call the verify_db_login()
function. The following PHP code demonstrates how you
begin the authentication of users in your realm: // Declare control variable.
$valid_user = false;
// Authenticate user.
if ((isset($_SERVER['PHP_AUTH_USER'])) && (isset($_SERVER['PHP_AUTH_PW'])))
if (verify_db_login($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']))
$valid_user = true;
This function opens a connection to the Oracle
database and checks whether the credentials are valid.
The verify_db_login() function returns true when
credentials are valid and false when not. When the
SYSTEM_USER table is missing, the code tells you to
check for the missing table. The main code for the Web
page is shown in the function: // Check for authorized account.
function verify_db_login($userid,$passwd)
{
// Attempt connection.
if ($c = @oci_connect(SCHEMA,PASSWD,TNS_ID))
{
// Return a row.
$s = oci_parse($c,"SELECT NULL
FROM system_user
WHERE system_user_name = :userid
AND system_user_password = :passwd
AND SYSDATE BETWEEN start_date
AND NVL(end_date,SYSDATE)");
// Encrypt password.
$newpassword = sha1($passwd);
// Bind variables as strings.
oci_bind_by_name($s,":userid",$userid);
oci_bind_by_name($s,":passwd", $newpassword));
// Execute the query.
if (@oci_execute($s,OCI_DEFAULT))
{
// Check for a validated user, also known as a fetched row.
if (oci_fetch($s))
return true;
else
return false;
}
else
{
// Print error when execution fails.
$errorMessage = "Check for a missing SYSTEM_USER table.<br />";
print $errorMessage;
}
// Close connection.
oci_close($c);
}
else
{
$errorMessage = oci_error();
print htmlentities($errorMessage['message'])."<br />";
}
}
There are two things to note about the
verify_db_function() function. First, the query returns
a null value, which eliminates processing any
unnecessary return values. Second, the clear text
password is encrypted using the sha1() function and
assigned to a local variable.
You now know how to build the required components for
basic HTTP/HTTPS authentication. The two caveats
associated with this authentication model are that you:
(1) have complete access to the realm once you
authenticate your credentials in a browser; and (2) can
only log out by closing all browser
windows.
Cookie and Session Model. The cookie
and session model is popular because you can let users
login and logout of Web applications without requiring
them to shutdown all of their browser windows. This
authentication model is also more complex than the basic
HTTP/HTTPS model. There are different ways that you can
implement cookie and session authentications.
The login and logout operations operate inside active
browsers. This operating context adds more complexity to
the cookie and session model. For example, the browser
backward, forward, and refresh buttons require special
handling in your code. A refresh button shouldn't
attempt to send a new user authentication more than
once. Likewise, a refresh button should not trigger new
authentication requests after a user has logged out of
an application. Unfortunately, they do unless the
program prevents it.
Calling a login PHP script, not an XHTML Web page is
the most direct way to guarantee a complete logout
operation in your Web application. A PHP script can
reset the session value whereas an XHTML Web page cannot
because it passes the prior session value when
submitting missing or new credentials to a target
page.
There are several predefined variables in PHP that
you can use to store globally scoped variables. One is
the $_SESSION array. It lets you add any name-value
pair, where the name becomes the index value to the
actual data value. The advantages of using the $_SESSION
array are simplicity and flexibility but the
disadvantages can involve conflicts with other
libraries.
The session_start() function returns the active PHP
session ID value. You must call the session_start()
function before the session_regenerate_id() function
because it actually calls the session_destroy()
function. The session_destroy() depends on the existence
of a PHP session ID and will raise an error when one
doesn't exist before you call it. Your call to the
session_regenerate_id() function with an actual true
parameter will reset the PHP session ID. You use runtime
error suppression to guarantee that calling the
session_regenerate_id() function doesn't raise an error
when no prior session exists in the context of the
browser. <?php
// Start and regenerate session.
session_start();
@session_regenerate_id(true);
$_SESSION['sessionid'] = session_id();
?>
The preceding scriptlet alters the session value in
the browser, and it will force new authentication with
the next click of the Login button. It
does this by replacing the previously authenticated PHP
session ID with a new session ID. The new PHP session ID
is transmitted as part of the URL to the next form.
There are two ways to manage database connections
once you establish your PHP session: One uses a
persistent connection between the PHP module and the
database and the other uses a non-persistent connection
between the two. Persistent connections let you start a
transaction scope that can span several Web requests,
and they end only when you issue a database commit
command. During the scope of a persistent connection,
you can run SQL and PL/SQL statements that lock rows
pending change or after an uncommitted change.
Non-persistent connections let you run SQL or PL/SQL
statements to query or change data between opening and
closing a connection, which occurs in a single Web
request. Data transactions limited by a single
connection are also known as autonomous transactions
because their duration is limited to the duration of the
connection.
These sample programs use non-persistent database
connections to query and transact against the Oracle
database. Consequently, all database transactions
perform as autonomous transactions.
The SignOnDB.php Web page, shown in Figure 5,
implements this type of PHP scriptlet before the XHTML
page. The XHTML rendering found in the SignOnDB.php form
is also found in the AddDbUser.php page as the
signOnForm() function.
You will put the PHP authentication logic in all Web
pages called after a user logs into the application. At
present all programming logic is in the AddDbUser.php
page, shown in Figure 6, but you can move the twelve
functions into one authentication library.
Your browser must accept cookies for these programs
to work. When cookies are disabled, all you can do is
login, logout, and fail to enter a new user because the
session values are lost between pages.
Experiment with Session Authentication.
You can experiment with the session identity
management by following these steps:
1. Open the session identification management
examples by using the following URL, assuming that you
placed the code in the htdocs directory: http://localhost/SignOnDB.php
2. You can use either of the seeded accounts
presented in the Basic HTTP/HTTPS authentication:

Figure
6 Cookie and Session Login page
3. You can now enter a new user into your credential
repository in the New User form, which
requires user name to be a string that is 6 to 10
characters long and starts with a letter:

Figure
7 Cookie and session Add New User page
4. After you add the new user, the AddDBUser.php
script will present you with a new copy of the
New User form. It will acknowledge
whether you successfully added a new user or explain
what rule the entry violated. You can connect to the
IDMGMT1 schema and run the following query to inspect a
new user entry: SELECT system_user_name, system_user_password FROM system_user;
Analyze the Session Authentication Code
The PHP program's logic accounts for the typical
nuances of the forward, backward and refresh browser
buttons. Figure 7 displays the rendered Web page. When
you call or refresh the form by using the browser
navigation buttons, the program determines whether (a)
the session is registered in the database model to the
current user, (b) the remote address is the same client
IP address from authentication, and (c) the session is
current. A session is current when the last related
database activity of the session occurred within the
last five minutes.
Both the initial sign on form and add user forms
check and verify a registered session before the program
logic looks for new user credentials and attempts to
authenticate the user. When the credentials are
authenticated, the SignOnDB.php script registers the new
session and calls the AddDbUser.php script. A refresh of
the AddDbUser.php script calls the signOnForm() function
that mimics the SignOn.php form's behavior. When the
AddDbUser.php script authenticates credentials, it
renders a page using the addUserForm() and when either
script repudiates credentials, they log a failed login
attempt and render a new sign on page.

Figure
8 Cookie and session authentication activity
diagram
The Web page contains two XHTML forms. One form lets
you enter a new user, validate that the credentials meet
guidelines (e.g., 6 to 10 character strings starting
with a letter), and inserts the credentials into the
database. The other form lets you opt to log out of the
application by calling the SignOnDB.php script, which
resets the session to prevent it appearing authenticated
in the database after a user logged out.
The Web page starts the session and assigns it to the
$_SESSION array, assigns any submitted credentials to
local variables, and then checks to see whether a
current authenticated session is available. This is done
by the following code: // Check for valid session and regenerate when session is invalid.
if ((get_session($_SESSION['sessionid'],$userid,$passwd) == 0) ||
(($_SESSION['userid'] != $userid) && ($userid)))
{
// Regenerate session ID.
session_regenerate_id(true);
$_SESSION['sessionid'] = session_id();
}
else
{
$authenticated = true;
}
The get_session() function opens a connection to the
database and queries a result set from the join of the
SYSTEM_USER and SYSTEM_SESSION tables. The results from
the query determine whether or not the session is
authenticated. Part of this verification process checks
to make sure that the request originates from the same
IP address. When authenticated, Web page variables are
assigned values from the query to process the page
request. At the same time, the LAST_UPDATE_DATE column
timestamp is updated by the update_session() function.
The attempt is logged by the record_session() function
to the OBSOLETE_SESSION table in the database when
authentication fails. // Get a valid session.
function get_session($sessionid,$userid = null,$passwd = null)
{
// Attempt connection and evaluate password.
if ($c = @oci_connect(SCHEMA,PASSWD,TNS_ID))
{
// Assign metadata to local variable.
$remote_address = $_SERVER['REMOTE_ADDR'];
// Return database UID within 5 minutes of session registration.
// The Oracle DATE data type is a timestamp where .003472222 is
// equal to 5 minutes.
$s = oci_parse($c,"SELECT su.system_user_name
, ss.system_remote_address
, ss.system_session_id
FROM system_user su JOIN system_session ss
ON su.system_user_id = ss.system_user_id
WHERE ss.system_session_number = :sessionid
AND (SYSDATE - ss.last_update_date) <=
.003472222");
// Bind the variables as strings.
oci_bind_by_name($s,":sessionid",$sessionid);
// Execute the query, error handling should be added.
if (@oci_execute($s,OCI_DEFAULT))
{
// Check for a validated user, also known as a fetched row.
if (oci_fetch($s))
{
// Assign unqualified values.
$_SESSION['userid'] = oci_result($s,'SYSTEM_USER_NAME');
// Check for same remote address.
if ($remote_address == oci_result($s,'SYSTEM_REMOTE_ADDRESS'))
{
// Refresh last update timestamp of session.
update_session($c,$sessionid,$remote_address);
return (int) oci_result($s,'SYSTEM_SESSION_ID'); }
else
{
// Log attempted entry.
record_session($c,$sessionid);
return 0;
}
}
else
{
// Record when not first login.
if (!isset($userid) && !isset($passwd))
record_session($c,$sessionid);
// Return a zero.
return 0;
}
else
{
// Print error when oci_execute() fails.
$errorMessage = "Check for a missing SYSTEM_USER or ";
$errorMessage .= "SYSTEM_SESSION tables.<br />";
print $errorMessage;
return 0;
}
// Close the connection.
oci_close($c);
}
else
{
$errorMessage = oci_error();
print htmlentities($errorMessage['message'])."<br />";
return 0;
}
}
You should note that the functions called from the
get_session() function share the database connection
opened to confirm an existing session. This goal is
accomplished by passing the connection as an actual
parameter to the other two functions. Managing the
database transaction scope in a single database
connection lets you manage multiple SQL and PL/SQL
statements as components of a transaction. This enables
functions to contain single subjects of your data
abstraction layer and lets you treat nested function
calls as subroutines.

Figure
9 Cookie and session Add New User Bad
Credential page
The next section of primary code in the Web page
renders different versions of the form because it serves
multiple purposes. Figure 6 shows the form rendered on
initial login to the application. Figure 9 demonstrates
the form rendered after attempting to enter a null user
name. The code calls the create_new_db_user() function
when appropriate to add new users to the ACL in the
SYSTEM_USER table, as shown: // Check whether the program should:
// -----------------------------------------------------------------
// Action #1: Verify new credentials and start a database session.
// Action #2: Continue a session on refresh button.
// Action #3: Provide a new form after adding a user.
// Action #4: Provide a new form after failing to add a user.
// -----------------------------------------------------------------
if (($authenticated) || (authenticate($userid,$passwd)))
{
// Assign inputs to variables.
$newuserid = @$_POST['newuserid'];
$newpasswd = @$_POST['newpasswd'];
// Set message and write new credentials.
if ((isset($newuserid)) && (isset($newpasswd)) &&
(($code = verify_credentials($newuserid,$newpasswd)) !== 0))
{
// Render empty form with error message from prior attempt.
addUserForm(array("code"=>$code
,"form"=>"AddDbUser.php"
,"userid"=>$newuserid));
}
else
{
// Create new user only when authenticated.
if (!(isset($userid)) && (isset($_SESSION['userid'])))
create_new_db_user($_SESSION['db_userid'],$newuserid,$newpasswd);
// Render fresh empty form.
addUserForm(array("form"=>"AddDbUser.php"));
}
}
else
{
// Destroy the session and force re-authentication.
session_destroy();
// Redirect to the login form.
signOnForm();
}
The nested if statement filters calls to the
create_new_db_user() function by ensuring that
$newuserid and $newpasswd variables are set. These two
variables can only be set in the AddDbUser.php Web page,
which means these cannot be called until after your user
has authenticated. This works on a subsequent call to
the AddDbUser.php Web page because clicking the
Add User button recursively calls the
same Web page. // Add a new user to the authorized control list.
function create_new_db_user($userid,$newuserid,$newpasswd)
{
// Attempt connection and evaluate password.
if ($c = @oci_connect(SCHEMA,PASSWD,TNS_ID))
{
// Check for prior insert, possible on Web page refresh.
if (!is_inserted($c,$newuserid))
{
// Encrypt password.
$newpassword = sha1($passwd);
// Return database UID.
$s = oci_parse($c,"INSERT INTO system_user
( system_user_id
, system_user_name
, system_user_password
, system_user_group_id
, system_user_type
, created_by
, creation_date
, last_updated_by
, last_update_date )
VALUES
( system_user_s1.nextval
, :newuserid
, :newpasswd
, 1
, 1
, :userid1
, SYSDATE
, :userid2
, SYSDATE)");
// Bind the variables as strings.
oci_bind_by_name($s,":newuserid",$newuserid);
oci_bind_by_name($s,":newpasswd", $newpassword);
oci_bind_by_name($s,":userid1",$userid);
oci_bind_by_name($s,":userid2",$userid);
// Execute the query, error handling should be added.
if (!@oci_execute($s,OCI_COMMIT_ON_SUCCESS))
{
// Print error when oci_execute() fails.
$errorMessage = "Check for a missing SYSTEM_USER table.<br />";
print $errorMessage;
}
}
// Close the connection.
oci_close($c);
}
else
{
$errorMessage = oci_error();
print htmlentities($errorMessage['message'])."<br />";
}
}
Inside of the create_new_db_user() function, the
function makes a call to the is_inserted() function.
This checks to make sure that the user does not already
exist before attempting to insert one into the
SYSTEM_USER table. Like the earlier nested function
examples, the is_inserted() function shares the local
connection for transaction control purposes. Also, the
sha1() function converts the clear text password to an
encrypted string before binding the user password to the
data manipulation variable.
After successfully inserting the new user, the
New User form renders itself again
waiting for you to insert another user or to click the
Log Out button. The Log Out
button returns you to the login screen, which
resets your session identifier.
Conclusion
Now that you have learned how identity management
works and how you can implement a basic identity
management solution, you should be comfortable with the
terminology, architecture, and approach to
authenticating your users.
You can now manage user authentication and access
equally, but all users are not equal. Some may have
unrestricted access, while most others have restricted
access privileges. Part 2 of this article shows you how
to link identity management with two technologies that
enable fine-grained access control.
Although the VPD feature is the "state of the art,"
the older technology, DBMS_APPLICATION_INFO, also works
in Oracle8i, Oracle9i, and Oracle
Database 10g Release 1. It is also the core
utility supporting Oracle E-Business 11i Suite
authentication. Both these technologies let you
implement fine grained access privileges and roles.
Go on to Part
2
Michael McLaughlin is the author of
Oracle Database 10g Express Edition PHP Web
Programming, and co-author of Oracle Database
10g PL/SQL Programming and Expert Oracle
PL/SQL by Oracle Press, and a professor of Computer
Information Technology at Brigham Young University —
Idaho. |