Put username in apache access_log with PHP and wit

2019-02-02 15:45发布

问题:

In the Apache log configuration it is possible to specify that the HTTP auth user name should be logged. Most PHP scripts have their own, cookie-based authentication. Is it possible in PHP to provide Apache with a HTTP auth username for logging purposes, even if the authentication is cookie-based? If yes, how would the code look like? If not, what are alternatives?

回答1:

Apache passes data between modules in notes. If you run PHP as an Apache module, you can use apache_note() to get and set notes. You can then include the %{note_name}n log format string to write this to the access log. This will not "leak" any data back to the client.

In PHP:

apache_note( 'username', $username );

In your server configuration:

LogFormat "%h %l %{username}n %t \"%r\" %>s %b" common_with_php_username
CustomLog logs/access_log common_with_php_username


回答2:

Since Apache 2.4.7 Apache allows you to copy a response-header to a note. So if you don't run PHP as an Apache module (but for instance use PHP-FPM), and you also don't want the log-value to be sent to the client (which would usually happen if you set it in a response-header), here's a way to do it:

php:

header('X-Username: '.$username);

httpd.conf:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{username}n\"" logfmtname

vhost.conf:

CustomLog logs/vhost-access_log logfmtname

# copy response-header value to note
Header note X-Username username
# unset response-header so client won't get it
Header unset X-Username


回答3:

A possibility is to store usernames & past session_ids somewhere else, and let the log write the cookie values in it (usually %{PHPSESSID}C), which you then can trace back.

Another option would be to send a header with the username back to the client, preferably right after your session_start:

PHP:

header('X-Php-Sess-User: '.$username);

Customlog:

%{X-Php-Sess-User}o


回答4:

Short of using an Apache handler to touch the internal auth* data structures, your best bet is to resort to environment variables. You would set a top-level environment variable using apache_setenv in your PHP code

apache_setenv('USERID','jrodriguez',true);

and then write the value to the log file with a LogFormat entry in your Apache config using "%{USERID}e" instead of "%u"

LogFormat "%v:%p %h %l %{USERID}e %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" envuid_combined
CustomLog /path/to/access.log envuid_combined

Of course, the real credentials when performing actual HTTP auth would be lost forever, so consider saving %u somewhere else -- either in a new field or in a parallel log file.