特定 Angular 路由上的 Nginx 403 错误

Nginx 403 Error on Specific Angular Route

所以我有一个 angular 应用程序,它有几条我可以轻松到达的路线。

但是,/admin 使我不知所措,因为我收到了 403 错误。工作路线的示例,在 /articles 负载时以完全相同的方式设置就可以了。

这是我的应用配置:

    app.config(['$stateProvider', '$locationProvider', '$urlRouterProvider',
    function($stateProvider, $locationProvider, $urlRouterProvider) {
        $stateProvider.
            ...
            state('articles', {
                url: '/articles',
                templateUrl: 'components/articles/templates/articles.tmpl.html',
                controller: 'ArticleController'
            }).
            state('articles/:id', {
                url: '/articles/:id',
                templateUrl: 'components/articles/templates/single-article.tmpl.html',
                controller: 'ArticleController'
            }).
            state('admin', {
                url: '/admin',
                templateUrl: 'admin/templates/admin.tmpl.html',
                controller: 'AdminController'
            }).
            state('admin.create', {
                url: '/create',
                templateUrl: 'admin/create/templates/create.tmpl.html',
                controller: 'AdminCreateController'
            }).
            ...
        $urlRouterProvider.otherwise('/');
        $locationProvider.html5Mode(true);
    }
]);

我知道罪魁祸首是 Nginx我知道它是用 html5Mode 触发的;所以我检查了我是如何重新路由到索引页面的,这一切看起来都很好(并且在网站上正常工作)作为我的 nginx 站点可用 conf:

server {

   listen 80;
   server_name app.local.dev;
   root "/vagrant/app";
   index index.html;
   location / {
       try_files $uri $uri/ /index.html;

   }

}

这是 Nginx 的错误日志示例:

2015/02/06 06:14:23 [error] 3361#0: *20 directory index of "/vagrant/app/admin/" is forbidden, client: 192.168.99.1,

我的文件结构似乎没有任何权限异常(/admin 文件所在的根文件夹:

-rw-r--r-- 1 vagrant vagrant  229 Feb  2 20:33 AdminController.js
-rw-rw-r-- 1 vagrant vagrant   90 Feb  2 05:18 AdminModule.js
drwxr-xr-x 1 vagrant vagrant  204 Feb  3 02:55 create
-rw-r--r-- 1 vagrant vagrant 6148 Feb  2 16:08 .DS_Store
drwxr-xr-x 1 vagrant vagrant  170 Feb  3 05:12 edit
drwxr-xr-x 1 vagrant vagrant  102 Feb  2 20:33 templates

/admin 模板文件:

-rw-r--r-- 1 vagrant vagrant 151 Feb  2 20:33 admin.tmpl.html

/articles 个文件所在的根文件夹:

-rw-r--r-- 1 vagrant vagrant 715 Feb  5 03:47 ArticleController.js
-rw-r--r-- 1 vagrant vagrant  94 Dec  3 18:29 ArticleModule.js
drwxr-xr-x 1 vagrant vagrant 136 Feb  6 04:19 templates

/articles 个模板文件:

-rw-r--r-- 1 vagrant vagrant 526 Feb  6 04:19 articles.tmpl.html
-rw-r--r-- 1 vagrant vagrant 453 Feb  5 22:35 single-article.tmpl.html

所以事情正在重新路由和正确写入。我可以访问我的主域,获取没有哈希的主页,然后四处点击并维护一个不包含哈希 (html5Mode) 的漂亮 url 并且(除了 /admin)能够刷新并重新 -通过 Angular.

正确加载该状态

但是,如果我将我的 app.config 管理状态更改为 url 的 /admins 它将神奇地工作,重新加载将正确刷新 /admins 并显示正确的视图。

state('admin', {
    url: '/admins', // works as expected and loads what was my /admin view with correct refreshing in Nginx
    templateUrl: 'admin/templates/admin.tmpl.html',
    controller: 'AdminController'
}).

那么 Nginx 中是否存在某种奇怪的保留 URL?我正在使用 Vagrant 并特别关闭了 sendfile,因为许多报告奇怪的缓存。是我的 nginx.conf 设置有误吗?我觉得我的 URL 重写工作正常,因为它在站点的其他任何地方都有效。 /articles 和不 /admin 的路由之间唯一的其他区别是 /admin 内部有嵌套状态,例如。 /admin/create/pages/.

您的逻辑路径似乎与您的 "physical" 路径冲突。

UiRouter 拦截客户端的请求。每次您尝试获取 "foo.bar/admin" 时,它都会检查路由 table 并显示 "uhm, this is registered as a logical path (client side), so it doesn't need to query the server"。 问题是,当你直接请求 "foo.bar/admin" 而不是导航到它时,nginx 是第一个收到请求的(因为 uiRouter 甚至不会被加载),并且因为你在服务器中使用相同的路径存储文件,而不是 returning index.html 文件,你的另一个

rules try_files $uri $uri/

具有优先权并尝试在您的服务器上找到它。但是当然,它找不到它,因为那里没有 'admin' 文件。我相信它不是 404,因为该路径实际上存在于服务器上,但它是一个目录,因此它不能 return 它,所以它会检测到 403。

一个可能的解决方案就是避免路径冲突,就像您将 'admin' 重命名为 'admins' 时所做的那样。由于 nginx 在服务器上找不到 'admins',它回退到 index.html.

其他解决方案是使用 gulp 或 grunt 之类的东西来压缩文件并避免有多个目录(因此路径冲突)。

最后,您可以重写一些规则以将 /admin 重定向到 index.html... 但我不会这样做。另外两个是更好的选择。

遗憾的是,我对 angular 没有太多经验,但我可以说,当您请求 url 时,例如 /admin nginx 会检查您在 try_files,即

$uri # check if there's a file called admin

当然你没有所以进入下一步

$uri/ #check if there's a directory called admin

找到了,因为你只提供了一个目录,所以它会检查来自

的索引
index index.html;

所以 nginx 试图找到 /admin/index.html 并且我认为它不存在,所以 nginx 回退到最后一件事是目录列表,但是因为你没有 autoindex on然后它回退到 403 错误,因为不允许目录索引。

如果您想跳过此步骤并提供 index.html 我假设它有一些与 angular 相关的代码,那么我建议的解决方案是完全删除 $uri/ 部分, 所以最后的 try_files 行是

try_files $uri /index.html;