VINO/WANG返回博客 ←

BLOG / POST

Nginx 如何区分不同设备访问

通过 Nginx 识别用户代理,实现对特定设备(如苹果设备)的访问控制。

  • nginx
  • ops

今天接到一个用户的需求

他希望能够屏蔽公司的苹果设备访问一些web应用。当苹果设备访问应用时给出提示:苹果设备禁止访问。

这里补充下,我们给客户做了10多个web应用,并通过nginx代理到端口6100上,通过不同的路径访问不同的应用,nginx 配置大致如下:

server{
 listen 6100;
 server_name 127.0.0.1;

 location /book {
    root /data/nginx/html/app;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
 }
 
 location /bank {
    root /data/nginx/html/app;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
 }
}

上述分别访问到 /data/nginx/html/app/book/data/nginx/html/app/bank 目录下的静态资源。

通过前端代码处理

在静态资源入口,加上 user agent 的判断,区分类型返回不同的页面,大致代码如下:

const app = document.querySelector("#app")

const platform = navigator.platform || navigator.userAgentData.platform

// 判断是否是苹果设备
if (/mac|ipone|ipad/i.test(platform)){
  app.innerHTML = "no permission"
}else {
  app.innerHTML = "hello"
}

虽然说这种方法也可以实现当前需求,但是这里需要修改将近10个web应用,意味着这10多个应用的代码都得修改,所以在前端代码中作修改并不太合适。

通过Nginx做处理

nginx 作为网关,同样可以获取到用户访问设备的 user agent。因此在nginx上拦截是个不错的选择。具体处理如下:

map $http_user_agent $is_apple {
  default 0;
  "~*iphone|ipad|ipod|Mac" 1;
}

server{
 listen 6100;
 server_name 127.0.0.1;

 location /no-permission {
  root /hjxz/nginx/html/app;
  index index.html index.htm;
  try_files $uri $uri/ /index.html;
 }

 location /book {
  if ($is_apple = 1){
    return 307 /no-permission
  }
  if ($is_apple = 0){
    root /hjxz/nginx/html/pc;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
 }
  location /bank {
  if ($is_apple = 1){
    return 307 /no-permission
  }
  if ($is_apple = 0){
    root /hjxz/nginx/html/pc;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
 }
}
  1. 定义 is_apple 变量,用户判断设备访问的型号
  2. is_apple 变量默认值是0,当 "~*iphone|ipad|ipod|Mac" 1; 当设备是苹果型号则返回1
  3. 添加一个 /no-permission 路径的映射,里面的静态文件内容是一个显示「没有权限」的html 文件
  4. is_apple 的值等于 1 时,重定向到 /no-permission 路径。

完。