A Sample Application Logging Class in PHP

Một phần của tài liệu Pro PHP Security phần 8 doc (Trang 38 - 45)

The following PHP class can be used to generate machine-parsable log files that include an arbitrary number of entries per request. It correlates the request time, session, action, and location with any number of events generated by the business logic of an application, and recognizes three levels of log messages: debug messages (which would be ignored by produc- tion servers), regular log messages, and alert messages (which are copied to an email address).

This code can be found also as ]`XXVc4]RddaYa in the Chapter 20 folder of the downloadable archive of code for Pro PHP Security at Yeea+ hhhRacVddT`^.

-0aYa

T]Rdd]`XXVcl Z_WcRdecfTefcV

acZgReVaReY, aReY`W]`XWZ]V

acZgReVSfWWVc.RccRj, RccRje`Y`]U]`XV_ecZVd

acZgReVUVSfX.72=D6, TRaefcVUVSfX]VgV]^VddRXVdZWUVdZcVU acZgReVR]VceE`, V^RZ]e`dV_UR]Vcede`

T`_decfTe`ccVbfZcVdRhcZeRS]VaReYWZ]V`cUZcVTe`cj

afS]ZTWf_TeZ`_PPT`_decfTeaReYUVSfX.72=D6R]VceE`.?F==l deRceeZ^Vc

eYZd/deRce.^ZTc`eZ^VECF6, UVeVc^Z_V]`XWZ]VaReY eYZd/aReY.aReY,

TYVT\e`^R\VdfcVaReYViZdedR_UZdhcZeRS]V ZWZdPhcZeRS]VeYZd/aReYl

eYc`h_Vh6iTVaeZ`_=`XTcVReZ`_WRZ]VUf_hcZeRS]VaReY, n

ZWaReYZdUZcVTe`cjfdVeZ^VdeR^aSRdVUWZ]V_R^V ZWZdPUZceYZd/aReYl

eYZd/aReY.eYZd/aReYUReVJ^]`X, n

dVeUVSfXW]RX eYZd/UVSfX.UVSfX,

SnyderSouthwell_5084.book Page 380 Tuesday, July 26, 2005 11:45 AM

C H A P T E R 2 0 ■ A D D I N G A C C O U N T A B I L I T Y T O T R A C K Y O U R U S E R S 381

dVeR]VceE`RUUcVdd eYZd/R]VceE`.R]VceE`, V_U`WT`_decfTe`c n

cVefc_dacVTZdVeZ^VV]RadVUdZ_TVdeRce afS]ZTWf_TeZ`_V]RadVUl

eZ^V.^ZTc`eZ^VECF6, V]RadVU.eZ^VeYZd/deRce, cVefc_V]RadVU,

n

]`XXVc4]RddaYaT`_eZ_fVd

The class begins by declaring some variables that are necessary for operation, and by defining a constructor method. This constructor notes the exact time of instantiation so that an elapsed time of execution can be generated later, it checks to see if the provided log file path exists and is writable, and it initializes the debug flag (which will determine whether debug-level messages are logged) and registers the email address, if provided, to send alert messages to.

Note that if a directory is provided at the aReY value, the ]`XXVc class generates a date- based filename for the log.

Because the logger captures an execution start time, and because you may need to start logging events right away, the ]`XXVc class should be instantiated as close as possible to the beginning of your script. The public V]RadVU method thus allows you to determine, to the microsecond, how much time has elapsed since the script was called and the ]`XXVc object was constructed.

The constructor method itself does not require any knowledge about the request. But since the logger does need to know these things, the class includes in the next section of the script an RTeZgReV method that collects them:

T`_eZ_fVd]`XXVc4]RddaYa ^RZ_]`XZ_eVcWRTV

acZgReVeZ^V, cVbfVdeeZ^V acZgReVdVddZ`_, dVddZ`_:5 acZgReVRTeZ`_, cVbfVdeVURTeZ`_

acZgReV]`TReZ`_, cVbfVdeVU]`TReZ`_

TR]]RTeZgReVe`UZdT`gVc^VeRUReR

afS]ZTWf_TeZ`_RTeZgReVRTeZ`_.?F==]`TReZ`_.?F==l XVeeZ^VdeR^a

eYZd/eZ^V.UReVJ^U9+Z+deZ^V, XVedVddZ`_:5

eYZd/dVddZ`_.dVddZ`_PZU,

SnyderSouthwell_5084.book Page 381 Tuesday, July 26, 2005 11:45 AM

382 C H A P T E R 2 0 ■ A D D I N G A C C O U N T A B I L I T Y T O T R A C K Y O U R U S E R S

UZdT`gVcRTeZ`_

ZWV^aejRTeZ`_l eYZd/RTeZ`_.RTeZ`_, n

V]dVl

ZWV^aejP86ELRTeZ`_Nl eYZd/RTeZ`_.P86ELRTeZ`_N, n

V]dVl

eYZd/RTeZ`_.PD6CG6CLC6BF6DEP>6E9@5N, n

n

UZdT`gVc]`TReZ`_

ZWV^aej]`TReZ`_l eYZd/]`TReZ`_.]`TReZ`_, n

V]dVl

eYZd/]`TReZ`_.PD6CG6CLC6BF6DEPFC:N, n

^R\VeYVWZcde]`XV_ecj

eYZd/]`XeYZd/RTeZ`_eYZd/]`TReZ`_, n

]`XXVc4]RddaYaT`_eZ_fVd

When the RTeZgReV method finishes collecting information about the request, it creates a log entry that includes the action and location.

It is important to note that the logged request time is fixed for the duration of the request, so that multiple log entries can be tied together as a group by timestamp. There is a separate mechanism (initialized with eYZd/deRce.^ZTc`eZ^VECF6 in the constructor and accessed using the V]RadVU method) for determining how much time has elapsed since the construction of the ]`XXVc object.

In the next section of the script, the ]`XXVc class continues by defining a private hcZeV method for adding entries to the log buffer, and then using that hcZeV method in the three public logging functions (UVSfX, ]`X, and R]Vce).

T`_eZ_fVd]`XXVc4]RddaYa

SRdZThcZeVWf_TeZ`_W`cfdVhZeYeYcVV]`X]VgV]d acZgReVWf_TeZ`_hcZeV^VddRXVl

hcZeeV_.72=D6,

V_T`UV_Vh]Z_VdZ_^VddRXV

^VddRXV.decPcVa]RTVRccRjM_McRccRjM_Mc^VddRXV,

SnyderSouthwell_5084.book Page 382 Tuesday, July 26, 2005 11:45 AM

C H A P T E R 2 0 ■ A D D I N G A C C O U N T A B I L I T Y T O T R A C K Y O U R U S E R S 383

TYVT\W`ccVaVReVU^VddRXVacVWZi`_]Rde]Z_V TfccV_e.T`f_eeYZd/SfWWVc,

]Rde.eYZd/SfWWVcLTfccV_e"N, cacVWZi.=Rde]Z_VcVaVReVU, cVaVRed.!,

cdfWWZi.eZ^Vd,

ZWdfSdec]Rde!dec]V_cacVWZi...cacVWZil TYVT\]Rde]Z_VSfe`_VW`cUfa]ZTReV^VddRXV

ZWeYZd/SfWWVcLTfccV_e#N...^VddRXVl

]ZdecVaVRed.Via]`UVdfSdec]Rdedec]V_cacVWZi, cVaVRed,

n n

TYVT\W`cWZcdecVaVRe`W]Rde]Z_V V]dVZW]Rde...^VddRXVl cVaVRed.",

n

ZWcVaVRed..!l RaaV_U_Vh^VddRXV

eYZd/SfWWVcLTfccV_eN.^VddRXV, hcZeeV_.ECF6,

n

V]dVZWcVaVRed.."l RaaV_UUfa]ZTReV^VddRXV

eYZd/SfWWVcLTfccV_eN.cacVWZicVaVRedcdfWWZi, n

V]dVl

cVhcZeVUfa]ZTReV^VddRXV

eYZd/SfWWVcLTfccV_e"N.cacVWZicVaVRedcdfWWZi, n

cVefc_hcZeeV_,

n V_U`WhcZeV^VeY`U ]`XXVc4]RddaYaT`_eZ_fVd

The hcZeV method does the work of determining the content of each log entry. Much of this work is concerned with managing the likely repetition of log entries. When hcZeV is called by one of the logging methods (which follow), it first encodes any linebreaks and/or carriage returns in the message, so that the message will be limited to a single line in the log file. It then checks to see whether the previous message generated a repeat statement. If it did, hcZeV then checks the line previous to that to see what message was repeated. If the current message is yet another repeat, hcZeV determines the number of repeats from the repeat statement, increments it by one, and writes it back to the buffer.

If the previous line is not a repeat statement, hcZeV checks to see whether the current line is itself a repeat of that previous line. If so, a new repeat statement is added to the buffer. If not, the message itself is added to the buffer.

SnyderSouthwell_5084.book Page 383 Tuesday, July 26, 2005 11:45 AM

384 C H A P T E R 2 0 ■ A D D I N G A C C O U N T A B I L I T Y T O T R A C K Y O U R U S E R S

If a message, rather than a repeat statement, was actually added to the buffer, the hcZeVmethod returns ECF6; otherwise, it returns 72=D6. This information will be used by theR]Vce method.

Now that the basic hcZeV functionality has been created, the three different public logging methods can be defined in the next portion of the script:

T`_eZ_fVd]`XXVc4]RddaYa eYcVV]`X]VgV]d+"UVSfX

afS]ZTWf_TeZ`_UVSfX^VddRXVl ZWeYZd/UVSfXl

eYZd/hcZeV^VddRXV, n

n

eYcVV]`X]VgV]d+#]`X afS]ZTWf_TeZ`_]`X^VddRXVl eYZd/hcZeV^VddRXV, n

eYcVV]`X]VgV]d+$R]Vce afS]ZTWf_TeZ`_R]Vce^VddRXVl

ZW^VddRXVhRdhcZeeV__`ecVaVReVUdV_UR]Vce ZWeYZd/hcZeV^VddRXVl

ZWV^aejeYZd/R]VceE`l

dfS[VTe.2]VceWc`^eYZd/RTeZ`_ReeYZd/]`TReZ`_, dV_e.^RZ]eYZd/R]VceE`dfS[VTe^VddRXV, n

n n

]`XXVc4]RddaYaT`_eZ_fVd

The first logging method, UVSfX, will hcZeV a message to the buffer only if the debugging flag is set. This permits developers to add messages to the log that will aid in development, but then globally turn off all of those extraneous messages when the application is moved into a production environment (where, presumably, all the bugs have been worked out).

The second method, ]`X, is the basic workhorse of the ]`XXVc class; it simply acts as a public wrapper for the private hcZeV method.

The third logging method, R]Vce, goes a step further for critical messages by sending them to the email address that was provided in the constructor. It will send only those messages that are not repeats, that is, where the hcZeV method returned the hcZeeV_ flag with a value of ECF6.

Once the buffer has been filled with log messages over the course of script execution, it needs to be flushed to disk. This is the work of the T`^^Ze method:

SnyderSouthwell_5084.book Page 384 Tuesday, July 26, 2005 11:45 AM

C H A P T E R 2 0 ■ A D D I N G A C C O U N T A B I L I T Y T O T R A C K Y O U R U S E R S 385

T`_eZ_fVd]`XXVc4]RddaYa

dVcZR]ZkVdSfWWVcR_UhcZeVdZee`WZ]V cVefc_dZ_edZkV`WhcZeeV_]`XZ_SjeVd afS]ZTWf_TeZ`_T`^^Zel

acVWZiVRTY]Z_VhZeYeZ^V dVddZ`_deR^a acVWZi.eYZd/eZ^VeYZd/dVddZ`_,

T`_gVceVRTYV_ecjZ_SfWWVcZ_e`_Vh]Z_V`W]`X W`cVRTYeYZd/SfWWVc2D]Z_Vl

ZWV^aej]Z_VT`_eZ_fV,

`feafe.acVWZi]Z_VMcM_, n

hcZeVe`UZd\

dZkV.WZ]VPafePT`_eV_edeYZd/aReY`feafe7:=6P2AA6?5, cVdVeSfWWVc

eYZd/SfWWVc.RccRj,

W`cUVSfXXZ_XYV]aWf]e`\_`hhYV_]`XhRdT`^^ZeeVU ZWeYZd/UVSfXl

V]RadVU.c`f_UeYZd/V]RadVU%,

eYZd/UVSfX4`^^ZeeVUacVgZ`fdSfWWVcReV]RadVUdVT`_Ud, n

cVefc_dZkV`W`feafe cVefc_dZkV,

n

V_U`W]`XXVcT]Rdd n

0/

The T`^^Ze method takes each of the entries collected in the buffer and writes them into the log file indicated by the value of aReY. As it does so, it prefixes each line with the request time- stamp and the session ID, so that all of the entries from one request can later be grouped together as a coherent unit. Once the entries are written, the buffer is cleared. If the logger is operating in debug mode, a message is added to the new buffer indicating that the previous buffer was flushed to disk.

As we mentioned before, the ]`XXVc class should be instantiated as near as possible to the start of a script, and the T`^^Ze method should be registered as a shutdown function so that it is called without fail at the end of every request, even if the request terminates early due to an ViZe call. To demonstrate this use, we include a simple controller script, shown next. This code can be found also as ]`XXVc4]Rdd5V^`aYa in the Chapter 20 folder of the downloadable archive of code for Pro PHP Security at Yeea+ hhhRacVddT`^.

SnyderSouthwell_5084.book Page 385 Tuesday, July 26, 2005 11:45 AM

386 C H A P T E R 2 0 ■ A D D I N G A C C O U N T A B I L I T Y T O T R A C K Y O U R U S E R S

-0aYa

fdVdVddZ`_d dVddZ`_PdeRce,

hcZeVUVSfX^VddRXVde`]`X0 UVSfX.ECF6,

]`RU]`XXVcT]Rdd

Z_T]fUVP`_TV]`XXVc4]RddaYa, Z_deR_eZReV]`XXVc

]`X._Vh]`XXVc Y`^V Td_jUVc ]`X UVSfXTd_jUVc1ViR^a]VT`^, cVXZdeVc]`X/T`^^ZeRddYfeU`h_Wf_TeZ`_

cVXZdeVcPdYfeU`h_PWf_TeZ`_RccRj]`XT`^^Ze, dVeRTeZ`_R_U]`TReZ`_

RTeZ`_.eVde,

]`TReZ`_.PD6CG6CLA9APD6=7N, RTeZgReV]`XXZ_X

]`X/RTeZgReVRTeZ`_]`TReZ`_, eYcVVcVaVReVUUVSfX^VddRXVd ]`X/UVSfXEVdeZ_XUVSfX, ]`X/UVSfXEVdeZ_XUVSfX, ]`X/UVSfXEVdeZ_XUVSfX, `_VcVXf]Rc]`X^VddRXV ]`X/]`XEVdeZ_X]`X, `_VR]Vce

]`X/R]VceEVdeZ_XR]Vce, Uf^a]`XXVc`S[VTeW`cUV^`

acZ_e-acV/acZ_ePc]`X"- acV/, ]`XhZ]]SVT`^^ZeeVURedYfeU`h_

0/

This extremely simple demonstration script simply instantiates a new logger object with some appropriate initialization values, registers the logger’s T`^^Ze method as a shutdown func- tion, and then adds some of each flavor of log message. In order to demonstrate the repeated- messages feature of the underlying hcZeV method, the same debug message is added three times. That the class is working can be seen by examining the log’s contents (note that the session ID is truncated for ease of viewing):

SnyderSouthwell_5084.book Page 386 Tuesday, July 26, 2005 11:45 AM

C H A P T E R 2 0 ■ A D D I N G A C C O U N T A B I L I T Y T O T R A C K Y O U R U S E R S 387

#!!&!(""!*+&(+!%RWWLNWW!eVde oTd_jUVc ]`XXVc4]Rdd5V^`aYa

#!!&!(""!*+&(+!%RWWLNWW!EVdeZ_XUVSfX

#!!&!(""!*+&(+!%RWWLNWW!=Rde]Z_VcVaVReVU#eZ^Vd

#!!&!(""!*+&(+!%RWWLNWW!EVdeZ_X]`X

#!!&!(""!*+&(+!%RWWLNWW!EVdeZ_XR]Vce

We see here how each line in the log contains a prefix consisting of time and session informa- tion, followed by the specific information being logged (here merely demonstration content).

Additionally, the R]Vce call sends the following email:

E`+TYd_jUVc1ViR^a]VT`^

DfS[VTe+2]VceWc`^eVdeRe]`XXVc4]Rdd5V^`aYa 5ReV+>`_"";f]#!!&!*+&(+!&!%!!65E 7c`^+_`S`Uj1WZ[Z]`TR]F_acZgZ]VXVUfdVc EVdeZ_XR]Vce

The R]Vce method could, of course, be customized to send additional mail headers so that the email could be automatically sorted into a folder, or to provide more information about the alert (such as the action and location) in order to give an administrator a better idea of why the alert has occurred.

Một phần của tài liệu Pro PHP Security phần 8 doc (Trang 38 - 45)

Tải bản đầy đủ (PDF)

(53 trang)