nginx区分手机与电脑浏览器并进入相应站点

本文要讲的的是如何使用nginx区分pc和手机访问不同的网站,是物理上完全隔离的两套网站(一套移动端、一套pc端),这样带来的好处pc端和移动端 的内容可以不一样,移动版网站不需要包含特别多的内容,只要包含必要的文字和较小的图片,这样会更节省流量。有好处当然也就会增加困难,难题就是你需要维 护两套环境,并且需要自动识别出来用户的物理设备并跳转到相应的网站,当判断错误时用户可以自己手动切换回正确的网站。

简单的服务器端实现方法

有两套网站代码,一套PC版放在/usr/local/website/web,一套移动版放在/usr/local/website/mobile。只需要修改nginx的配置文件件,nginx通过UA来判断是否来自移动端访问,实现不同的客户端访问不同内容。

这种方法的缺点是移动端和PC端用同一个域名,存在黑帽的嫌疑,而且UA并不是总是判断的准确,如果判断错误的情况下,用户不能手动修改访问的网站类型。

关键的Nginx配置如下:

location / {
  #默认PC端访问内容
  root /usr/local/website/web;
  #如果是手机移动端访问内容
  if ( $http_user_agent ~ "(MIDP)|(WAP)|(UP.Browser)|(Smartphone)|(Obigo)|(Mobile)|(AU.Browser)|(wxd.Mms)|(WxdB.Browser)|(CLDC)|(UP.Link)|(KM.Browser)|(UCWEB)|(SEMC\-Browser)|(Mini)|(Symbian)|(Palm)|(Nokia)|(Panasonic)|(MOT\-)|(SonyEricsson)|(NEC\-)|(Alcatel)|(Ericsson)|(BENQ)|(BenQ)|(Amoisonic)|(Amoi\-)|(Capitel)|(PHILIPS)|(SAMSUNG)|(Lenovo)|(Mitsu)|(Motorola)|(SHARP)|(WAPPER)|(LG\-)|(LG/)|(EG900)|(CECT)|(Compal)|(kejian)|(Bird)|(BIRD)|(G900/V1.0)|(Arima)|(CTL)|(TDG)|(Daxian)|(DAXIAN)|(DBTEL)|(Eastcom)|(EASTCOM)|(PANTECH)|(Dopod)|(Haier)|(HAIER)|(KONKA)|(KEJIAN)|(LENOVO)|(Soutec)|(SOUTEC)|(SAGEM)|(SEC\-)|(SED\-)|(EMOL\-)|(INNO55)|(ZTE)|(iPhone)|(Android)|(Windows CE)|(Wget)|(Java)|(curl)|(Opera)" )
  {
    root /usr/local/website/mobile;
  }
  index index.html index.htm;
}

推荐的nginx区别手机和PC访问方法

利用前端js和后端nginx配合,js通过设置cookie来设定当前访问哪页面。

增加设置cookie的js代码,这段代码需要在移动网站和PC网站的所有页面都要放置。

function createCookie(name, value, days, domain, path) {
  var expires = '';
  if (days) {
    var d = new Date();
    d.setTime(d.getTime() + (days*24*60*60*1000));
    expires = '; expires=' + d.toGMTString();
  }
  domain = domain ? '; domain=' + domain : '';
  path = '; path=' + (path ? path : '/');
  document.cookie = name + '=' + value + expires + path + domain;
}

function readCookie(name) {
  var n = name + '=';
  var cookies = document.cookie.split(';');
  for (var i = 0; i < cookies.length; i++) {
    var c = cookies[i].replace(/^\s+/, '');
    if (c.indexOf(n) == 0) {
      return c.substring(n.length);
    }
  }
  return null;
}

function eraseCookie(name, domain, path) {
  setCookie(name, '', -1, domain, path);
}

nginx增加如下配置,根据UA和cookie判断当前是移动端还是PC端访问

if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
  set $mobile_request '1';
}
if ($http_cookie ~ 'mobile_request=full') {
  set $mobile_request '';
}
if ($mobile_request = '1') {
  rewrite ^.+ http://m.lvtao.net$uri;
}

移动版页面添加PC版链接

默认用户进来时会先判断UA,如果是手机端访问就会进入手机版,但也会存在误判进入手机版或者需要更多信息进入PC版,那么就需要在移动版的页面放入代码,让用户可以从移动版切换到web版并且下次访问会保留设置。

<a onclick="setCookie('iphone_mode', 'full', 1, 'lvtao.net')" href="http://www.lvtao.net">电脑版</a>

如果用户访问不正确时,点击电脑版链接就可以进入PC版网站,并且24小时内再次访问会记忆上次访问的网站类型设置。

PC版网站增加访问手机版的链接

在PC版的网站适当的地方加入下面的链接让用户可以切换到手机版的网站。

<a onclick="deleteCookie('mobile_mode', 'lvtao.net');" href="http://m.lvtao.net">手机版</a>

完整的nginx端配置,当然是去掉了与本文功能无关的配置,并不是一个完可用的配置,只是给大家一个整体的框架。

PC版网站配置

upstream app_server {
  server 0.0.0.0:9001;
}

server {
  listen 80;
  server_name www.lvtao.net;

  root /path/to/main_site;
  # ...

  location / {
    proxy_set_header X-Real-IP $remote_addr;
    # ...

    if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
      set $mobile_request '1';
    }
    if ($http_cookie ~ 'mobile_request=full') {
      set $mobile_request '';
    }
    if ($mobile_request = '1') {
      rewrite ^.+ http://m.lvtao.net$uri;
    }

    # serve cached pages ...

    if (!-f $request_filename) {
      proxy_pass http://app_server;
      break;
    }
  }
}

手机移动版配置

upstream m_app_server {
server 0.0.0.0:9001;
}

server {
  listen 80;
  server_name m.lvtao.net;

  root /path/to/mobile_site;
  # ...

  location / {
    proxy_set_header X-Real-IP $remote_addr;
    # ...

    if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
      set $mobile_request '1';
    }
    if ($http_cookie ~ 'mobile_request=full') {
      set $mobile_request '';
    }
    if ($mobile_request != '1') {
      rewrite ^.+ http://www.lvtao.net$uri;
    }

    # serve cached pages ...

    if (!-f $request_filename) {
      proxy_pass http://m_app_server;
      break;
    }
  }
}