To precisely control the download permissions (preventing leeching, leeching, downloading, downloading, deducting points, and other virtual currencies), there are several methods in use:
1. Use rewrite to constantly change the url of the downloaded file and insert many meaningless characters;
2. Verify the download link or cookie;
3. Read and return the content to the client through a server program (such as a PHP file) and an open file.
The first method is stupid and thankless;
The second method is very easy to crack, because referer and cookie are sent by the client, which can be easily forged, and thunder is already familiar with this;
The third method is feasible and effective. All files are read and sent by a program. The permission can be verified before reading, but the download process always occupies a cgi thread, in addition, the general cgi language has poor IO performance and slow speed, occupying a large amount of resources on the server, resulting in extremely low overall efficiency and difficulty in large-scale application.
For this reason, I have studied the implementation mechanism of csdn download channels.
The csdn download channel can effectively verify permissions, deduct points, and does not exclude downloading clients such as thunder. The points are not deducted for downloading the same file by the same user, in addition, the actual address of the file is never exposed during the download, and the same download URL is completely unavailable to other places, which can be said to be ideal.
I chose a file for testing and the download url is: http://dldx.csdn.net/fd.php? I = 573624740728082 & s = 4fc2450ca769a0ebd9237b6f98791679
This url sends two encrypted parameters to the fd. php file on the NAS server, which should contain the user logon information (user ID and sid) and the ID number of the target file.
Use thunder to download this file and intercept the returned header information:
Host: dldx.csdn.net
Pragma: no-cache
Range: bytes = 0-
Referer: http://d.download.csdn.net/down/2474072/waf9898
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1 ;)
HTTP/1.1 206 Partial Content
Server: nginx/0.7.65
Date: Tue, 22 Jun 2010 07:08:21 GMT
Content-Type: "application/octet-stream; charset = UTF-8 ″
Content-Length: 667747
Last-Modified: Mon, 21 Jun 2010 23:45:02 GMT
Connection: keep-alive
Content-Disposition: attachment; filename+dnf%e6%82%a0%e6%82%a05%5b1%5d.7.rar"
Expires: 0
Cache-Control: must-revalidate, post-check = 0, pre-check = 0
Content-Range: bytes 0-667746/667747
The actual path of the target file has never been exposed, rather than the header redirection method used by the general Download System. In addition, there is a RENAME signal. The program used by the server is nginx/0.7.65.
Based on this information, google found this article: http://kovyrin.net/2006/11/01/nginx-x-accel-redirect-php-rails/
Obviously, csdn uses the nginx X-Accel-Redirect mentioned in this article.
Explain the entire process:
Step 1. The client requests the http://dldx.csdn.net/fd.php and transmits relevant information;
Step 2: fd. php identifies the visitor's identity and requested resources based on the information transmitted, and then verifies the client's IP address to further determine its permissions. If the client has the right to download this file, add X-Accel-Redirect: (the actual path of the file) to the HTTP header, and add head Content-Type and Content-Disposition :;
Step 3: nginx returns a response from fd. php and finds a header with X-Accel-Redirect. Then, based on the path information recorded in this header, open the target file;
Step 4: nginx returns the content of the opened file to the client.
In this way, all operations such as permission check and credit deduction can be completed in step 2, and fd. after php returns the header with X-Accel-Redirect, the execution has been terminated, and the rest of the file transfer work is taken over by nginx, at the same time, the information in the X-Accel-Redirect header is deleted by nginx and will not be returned to the client, so it will not be exposed (in fact, the target file can be stored in a directory that cannot be accessed through the web ), nginx uses sendfile () to open static files. Therefore, nginx has a high IO efficiency, which is N ++ times faster than php's IO.
This is an elegant, effective, and efficient implementation solution.
Because no nginx server has been set up, I hope to achieve this function in apache, so I looked up there is a similar mod, and found a mod_xsendfile: http://tn123.ath.cx/mod_xsendfile, its implementation mechanism is basically the same as that of nginx's X-Accel-Redirect.
Download and test on the local machine.
1. Load mod_xsendfile. Move the file mod_xsendfile.so to the apache/modules directory and add the following content to httpd. conf.
LoadModule xsendfile_module modules/mod_xsendfile.so
XSendFile On
Xsendfileallowabve On
2. Use PHP to call X-sendfile. The Code is as follows:
Receives and decrypts _ GET data;
Verify uid, sid, and file id;
If verification is successful:
{
Deduct points and count statistics;
Header ('content-Type :( target file Type )');
Header ('content-Disposition: attachment; filename = "(name of the file you want to download )"');
Header ('x-Sendfile: (the actual path of the target file. Use an absolute path, for example, "E:/www/dl/test.rar". This path can be a directory inaccessible to the web ") ');
Exit;
}
If it fails:
{
Returns a prompt html file to the client;
}
?>
3. Construct a download url and use thunder to download the file. Once the verification conditions (such as changing the Client IP address) are met, Thunder can only download the file with an error message.
The following solutions can be used in practical applications:
1. store all the target files in server B, which does not require a database and can only access a certain entry file (such as a http://dldx.csdn.net/fd.php) through the web ), use apache to implement X-Sendfile in this file;
2. The website file (php and html), and the database runs on server A (of course the database can also set up another server), which is responsible for constructing something similar to http://dldx.csdn.net/fd.php? I = 573624740728082 & s = 4fc2450ca769a0ebd9237b6f98791679 url;
3. After server B receives the preceding URL, it analyzes the Client IP address, remotely connects to the database of server A, and analyzes the uid, sid, file id, and Client IP address matching, if points are deducted, download is allowed. Otherwise, an error is returned.
This solution can ultimately achieve the following goals:
1. the target file cannot be accessed directly through the web in any way, and thunder cannot;
2. Like http://dldx.csdn.net/fd.php? I = 573624740728082 & s = 4fc2450ca769a0ebd9237b6f98791679 URL is not universal. Only specific users can access specific files from specific IP addresses. Even if thunder stores this URL, there is no way to suck blood (only files with an error prompt can be downloaded );
3. The file storage and database servers are separated to facilitate maintenance;
4. The speed and efficiency are perfect, without any verification errors or occupying too much server resources.
See http://kuigg.com/xiazai-kongzhi