2015-04-17 120 views
1

從Apache遷移到Nginx時,.htaccess文件中的某些規則必須'轉換'爲Nginx的配置文件。 一個問題,我似乎無法來解決,一個例子是解釋最簡單的方法:是否存在與Apaches的{ENV:REDIRECT_STATUS}等效的Nginx環境變量?

請求http://www.domain.com/nginx在內部被阿帕奇改寫爲index.php?option=com_content&view=article&id=145 現在我想阻止請求定向到index.php?option=com_content所以頁面僅可通過http://www.domain.com/nginx以避免重複的內容。在Apache中,這是通過使用這些.htaccess規則實現的:

# Check if it's the first pass to prevent a loop. In case of first pass, the environment variable contains nothing 
# If http://www.domain.com/nginx already internally has been rewritten to index.php?option=com_content&view=article&id=145 {ENV:REDIRECT_STATUS} contains '200' and the request is allowed to be processed 
RewriteCond %{ENV:REDIRECT_STATUS} ^$ 
# Check if the query string contains requests for the page 
RewriteCond %{QUERY_STRING} ^index.php?option=com_content&view=article&id=145 [NC] 
# If conditions apply, reject request 
RewriteRule .* 404 [L] 

在Nginx中,是否有這樣一個環境變量,我可以使用? 或者我應該以完全不同的方式來解決這個問題?

編輯1: 在現實生活中,它不僅僅是一個頁面,而是一個動態的Joomla網站,有很多頁面。我測試其中工程以上,但其意圖是阻止在index.php的所有請求option_content &視圖=文章& ID = *

編輯2: 這是工作NGINX配置文件:

server { 
    listen 80 default_server; 
    listen [::]:80 default_server ipv6only=on; 

    root /usr/share/nginx/html/domainname; 
    index index.php index.html index.htm; 
    server_name domainname.com; 

    server_name localhost; 

    location/{ 
      try_files $uri $uri/ /index.php?$args; 
    } 

    # deny running scripts inside writable directories 
    location ~* /(images|cache|media|logs|tmp)/.*\.(php|pl|py|jsp|asp|sh|cgi)$ { 
      return 403; 
      error_page 403 /403_error.html; 
    } 

    ## give 404 header & redirect to custom errorpage without changing URL ## 
    error_page 404 = /404_custom.php; #global error page, script handles header 
    error_page 500 502 503 504 /50x.html; 

    location =/index.php { 
     set $arg_set "${arg_option}___${arg_view}___${arg_id}"; 
     if ($arg_set ~* "^(((\w|-)+?)___){2}((\w|-)+?)$") { 
      return 404; 
     } 
      try_files $uri =404; 
      fastcgi_split_path_info ^(.+\.php)(/.+)$; 
      fastcgi_pass unix:/var/run/php5-fpm.sock; 
      fastcgi_index index.php; 
      include fastcgi_params; 
    } 

    location ~ \.php$ { 
     try_files $uri =404; 
     fastcgi_split_path_info ^(.+\.php)(/.+)$; 
     fastcgi_pass unix:/var/run/php5-fpm.sock; 
     fastcgi_index index.php; 
     include fastcgi_params; 
    } 
} 
+0

有指令'內部'http://nginx.org/r/internal –

回答

2

Apache方法在這裏不起作用,但還有很多其他方法可以解決這個問題,具體取決於您要實施多少個這樣的規則以及其他一些條件。在一般情況下,我會使用這樣的:

map "${arg_option}___${arg_view}___${arg_id}" $show404 { 
    default 0; 

    # Put here the argument value sets of the pages 
    # you want to hide - one set per line 
    "com_content___article___145" 1; 
} 

server { 
    ... 

    location /nginx { 
     rewrite ^.*$ /index.php?option=com_content&view=article&id=145 break; 
     proxy_pass ... 
    } 

    location =/index.php { 
     if ($show404) { 
      return 404; 
     } 

     proxy_pass ...; 
    } 

    ... 
} 

編輯:

如果你想阻止所有請求到index.php,其中參數「選項」,「查看」和「ID 「都存在,不管他們的價值觀,你可以使用這樣的事情:

location =/index.php { 
    set $arg_set "${arg_option}___${arg_view}___${arg_id}"; 

    if ($arg_set ~* "^(((\w|-)+?)___){2}((\w|-)+?)$") { 
     return 404; 
    } 

    proxy_pass ... 
} 

如果這些參數的一些值應進行檢查,只需修改正則表達式以滿足您的purpuse:

location =/index.php { 
    set $arg_set "${arg_option}___${arg_view}___${arg_id}"; 

    if ($arg_set ~* "^com_content___article___(\d+)$") { 
     return 404; 
    } 

    proxy_pass ... 
} 

此外,在您的情況地圖可以用來簡化配置,這樣你就不必添加另一個地點的每一篇文章,而不是封裝全部重寫規則在一個映射塊這樣的:

map "$request_uri" $real_args { 
    default ""; 

    "~*^/nginx"   option=com_content&view=article&id=145; 
    "~*^/some_article"  option=com_content&view=news&id=123; 
    "~*^/another_article" option=com_content&view=article&id=515; 
} 

server { 
    ... 

    location/{ 
     if ($real_args) { 
      rewrite ^.*$ /index.php?$real_args break; 
     } 

     proxy_pass ... 
    } 

    location =/index.php { 
     # See above 
    } 

    ... 
} 

編輯2:

對於一個或兩個例外,你可以提高你的正則表達式,使用negative look-ahead

if ($arg_set ~* "^(((\w|-)+?)___){2}((?!175$)(\w|-)+?)$") { 
    return 404; 
} 

但是,如果你期望有很多這樣的URL,你必須在你的配置中引入地圖。否則,你的正則表達式會變得太複雜和難以管理。在這種情況下,配置是這樣的:

map "${arg_option}___${arg_view}___${arg_id}" $exception { 
    default 0; 

    "com_content___article___175" 1; 
    "com_content___news___188" 1; 
    "something___else___211" 1; 
} 

server { 
    ... 

    location =/index.php { 
     set $arg_set "${arg_option}___${arg_view}___${arg_id}"; 

     if ($exception) { 
      break; 
     } 

     if ($arg_set ~* "^(((\w|-)+?)___){2}((\w|-)+?)$") { 
      return 404; 
     } 

     proxy_pass ...; 
    } 
    ... 
} 

這似乎有點違反直覺,但是這只是如何「如果」的作品在Nginx的。如果Nginx在第一個「if」塊中遇到中斷,則不會評估第二個「if」。

+0

謝謝你的答案。我給出的例子是爲了清晰起見而簡化了這個過程。在現實生活中,這不僅僅是一個頁面,而是一個擁有大量頁面的動態網站。我測試了上述哪些工作,但其目的是阻止index.php上的所有請求?option_content&view = article&id = * 這可以通過map完成嗎? –

+1

@cavuyk在這種情況下,你根本不需要使用地圖。只需根據適當的正則表達式檢查您的請求參數,並在匹配的情況下返回404。我已經更新了原來的答案。 –

+0

這個配置的工作原理(上面發佈的問題),你的回答接受,謝謝。但是,我還不明白爲什麼index.php上的直接請求被阻止,而CMS仍然可以使用index.php。是否可以描述內部處理,以便我能夠理解它? –