通过Nginx进行基于子域的用户帐户管理

ljsrvy3e  于 2022-11-21  发布在  Nginx
关注(0)|答案(1)|浏览(169)

我已经经历了不同的职位有关我的问题陈述,但没有一个似乎回答了我的问题,也许这也有助于其他人。

问题陈述:

我正在尝试设置基于子域的用户空间,其中foo.myportal.com将指向用户 foo 空间,bar.myportal.com将指向用户 bar 空间。
我不想使用'.htaccess',因为我的应用程序技术堆栈包含在Nginx,Angular,NodeJS上。
其中Nginx指向Angular应用和NodeJSAPI服务 (由Angular应用使用)

方法“A”:

在这个例子中,我们依赖于一个域,需要管理Nginx规则来满足这两个需求,这是一个棘手的部分。

server{
    listen 80 default_server; 
    server_name _;
    return 301 https://$host$request_uri;
}

server{
    listen 443 default_server; 
    server_name myportal.com;
    ...
    # SSL Certificate configurtion here ...
    ...
}

##############################################
# Handling account specific subdomain mapping

server{
    listen 80;
    server_name *.myportal.com;
    return 301 https://$host$request_uri;
    
}

server{
    listen 443 default_server; 
    
    server_name ~^(?<acc_id>.+)\.myportal\.com$
    
    #...
    # SSL Certificate conf.
    #...
    
    location / {                                # <=== Is this approach fine?
      if($cc_id = "identity"){
           proxy_pass http://127.0.0.1:8000;
      }
      if($acc_id = "api_services"{
           proxy_pass http://127.0.0.1:9000;
      }
      rewrite ^/$ https://myportal.com/$acc_id;  # <=== Will this fallback work at the end?
    }
    
}

方法“B”:

在这个场景中,我们使用多个域,以防方法:B失败。真的很期待听到Maven的反馈。
还是建议使用NodeJS来处理子域?如https://www.npmjs.com/package/express-subdomain中所示
我在AWS上设置了整个过程。

fruv7luv

fruv7luv1#

编辑

在评论之后,Nah更好地解释了他的需求。所以你想把nginx的请求代理到一个服务来处理Angular App。在这种情况下,你想做的是接收一个类似如下的请求:user1.myportal.com并将其代理到http://<IP>:<PORT>/user1形式的服务。

http {
   # Handle angular Single page Application.                                                                                                                                                                                                                                                                                                                          
   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name ~^(?<user_id>.+)\.myportal\.com$;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
     location / {                                                                                                                                                                                                                                                                                                                     
       proxy_pass http://12.12.12.12:3000/$user_id$request_uri                                                                                                                                                                                                                                                             
     }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
   }
   
   
   # handle api.myportal.com and identity.myportal.com                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name  api.myportal.com;
     location / {
       proxy_pass http://127.0.0.1:9000;
     }
   }

   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name  identity.myportal.com;
     location / {
       proxy_pass http://127.0.0.1:8000;
     }
   }
 }

如您所见,您应该使用server_name正则表达式中的user_id变量来构建proxy_pass指令的路径。
变量$request_uri用于处理所有带参数的路径,这样像user1.myportal.com/path/to/something?key=value这样的URL就可以被代理到12.12.12.12:3000/user1/path/to/something?key=value
上面的例子是有效的,因为proxy_pass指令与IP地址一起使用,NGINX可以解析它。如果你想使用主机名,你必须使用declare a resolver

原始答案

你几乎做到了。我没有看到的是一个适当的配置来服务(或代理)Angular 应用程序(这只是由静态资产)。
另外,你不需要使用奇数的if statements。最好在它们自己的服务器部分定义所有的子域。Nginx会优先考虑带有“确切名称”的server_names,然后是通配符和正则表达式。(here你可以找到更多关于这方面的信息)。
最后,我不明白你是希望用户使用user1.myportal.com这样的自定义子域进行第一次访问,然后重定向到myportal.com/user1,还是希望他们继续使用原来的url(user1.myportal.com)进行导航。我会选择第二种方法,因为它更通用,从用户的Angular 来看可能不那么奇怪。
我想,使用这两种方法,Angular 应用程序逻辑必须准备好知道用户名在路径起点的主机(myportal.com/user1)之后,或者在子域(user1.myportal.com)中。
我的解决方案不需要为您的服务提供辅助域。如果您愿意,您可以使用它们,但这不是必需的,它只是关于选择,没有更好的方法来实现这一点。

溶液A -〉

Angular应用程序与user1.myportal.com匹配,然后重定向到myportal.com/user1

http {
   # Handle angular Single page Application.                                                                                                                                                                                                                                                                                                                          
   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name myportal.com;                                                                                                                                                                                                                                                                                                    
     root /var/www/html;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
     index index.html;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
     location / {                                                                                                                                                                                                                                                                                                                     
       try_files $uri $uri/ $uri.html /index.html;
       # if you want here you can proxy pass to any service that is serving your angular static assets instead of using the try files directive.                                                                                                                                                                                                                                                                              
     }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
   }
   
   # Redirect user1.myportal.com like domains to myportal.com/user1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name  ~^(?<user_id>.+)\.myportal\.com$;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
     location / {                                                                                                                                                                                                                                                                                                                     
       return 301 http://myportal.com/$user_id;                                                                                                                                                                                                                                                                                 
     }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
   }
   # handle api.myportal.com and identity.myportal.com                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name  api.myportal.com;
     location / {
       proxy_pass http://127.0.0.1:9000;
     }
   }

   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name  identity.myportal.com;
     location / {
       proxy_pass http://127.0.0.1:8000;
     }
   }
 }

这种方法可以工作,但我觉得有点奇怪,用户将被重定向到一个新的页面。而且,你可能会有问题处理路径。我想你希望像user1.myportal.com/pictures的URL应该被重定向到user1.myportal.com/user1/pictures。要处理这个问题,你应该把return 301 http://myportal.com/$user_id;改为像return 301 http://myportal.com/$user_id$request_uri;

溶液B -〉

Angular应用程序与user1.myportal.com匹配。不涉及重定向,用户使用原始URL继续导航

http {
   # Handle angular Single page Application.                                                                                                                                                                                                                                                                                                                          
   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name ~^(?<user_id>.+)\.myportal\.com$;                                                                                                                                                                                                                                                                                                    
     root /var/www/html;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
     index index.html;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
     location / {                                                                                                                                                                                                                                                                                                                     
       try_files $uri $uri/ $uri.html /index.html;
       # if you want here you can proxy pass to any service that is serving your angular static assets instead of using the try files directive.                                                                                                                                                                                                                                                                              
     }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
   }
   
   
   # handle api.myportal.com and identity.myportal.com                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name  api.myportal.com;
     location / {
       proxy_pass http://127.0.0.1:9000;
     }
   }

   server {                                                                                                                                                                                                                                                                                                                         
     listen 80;                                                                                                                                                                                                                                                                                                                   
     server_name  identity.myportal.com;
     location / {
       proxy_pass http://127.0.0.1:8000;
     }
   }
 }

正如你所看到的,第二个解决方案是不使用任何重定向。我会选择解决方案B,它对用户来说更干净和方便。而且你不必处理“路径问题”。像user1.myportal.com/pictures这样的URL就可以了。同样:我假设您可以控制Angular Single Page Application的逻辑(和路由器),并且您知道对于单页应用程序,您必须始终为每个路径提供index.html文件。然后,客户端逻辑负责根据URL路径将用户路由到正确的视图,如果需要,还可以路由到URL子域。
我的两个解决方案都只显示了所需的基本配置。SSL,https到http重定向和微调参数都不包括在内,以给予你一个简洁但有用的原型。

相关问题