使用nginx搭建多臺虛擬主機模擬統一驗證(共享cookie的方式)

寫博客的緣由:太晚了,而舍友的呼嚕聲驚天動地,沒法入睡。html

環境:tornado,linux(linux mint 類ubuntu),nginx, python2.7python

首先是講一下nginx搭建多臺虛擬主機的過程,大體的步驟以下:linux

  這裏我配置了三個網站他們分別是:nginx

  #new host for distribute course experienceweb

  172.18.43.223 www.auth.my.com(端口爲8000)
  172.18.43.223 www.a1.my.com(端口爲8010)
  172.18.43.223 www.a2.my.com(端口爲8020)ubuntu

  172.18.43.223爲個人電腦在互聯網上的ip地址,你能夠經過在終端下執行ifconfig命令查看你當前的電腦的ip地址瀏覽器

  同時須要將這些網站的配置信息添加到/etc/hosts文件中,如圖:
服務器

  

  至於/ect/hosts文件是幹什麼用的,能夠看這裏cookie

  1.  在nginx(ubuntu下爲/etc/nginx.conf)的配置文件裏面配置多臺虛擬主機(server),形如:
    server {
      配置信息
    }

    裏面server_name項就是你要在瀏覽器輸入的網址,proxy_pass爲你指定哪一個upstream給這臺虛擬主機,這裏爲frontends
  2. 而後就是配置真正可以提供服務的地方了,那就是配置upstream了,其配置以下:

  前面的www.auth.my.com代理的upstream就是frontends裏面的127.0.0.1:8000(真正提供服務的網站)了app

總結一下,先是訪問nginx的某個虛擬主機,虛擬主機(上例子就是www.auth.my.com,因爲是網址,不是ip地址,因此這個時候nginx先是到/etc/hosts裏面找www.auth.my.com的ip地址,若是沒有找到則是向dns服務器求助,由於咱們以前已經在/etc/hosts裏面規定了www.auth.my.com的ip地址,因此咱們就有了www.auth.my.com對應的ip地址爲172.18.43.223 )就會根據配置文件(/etc/nginx.conf)裏面的配置信息來尋找真正提供服務的服務器(上例就是127.0.0.1:8000了),一樣方法能夠配置www.a1.my.com和www.a2.my.com.這樣以後就是配置好虛擬主機了。

 

2.模擬統一驗證平臺

  關於什麼是統一驗證和單點登陸及其原理,能夠看這裏

  

  這裏我講一下個人實現,我這裏的www.a1.my.com和www.a2.my.com對應的是應用系統1和應用系統2,www.auth.my.com對應的是認證系統,以cookie共享的方式實現統一是這樣子的,假設用戶不能直接訪問認證系統,若是用戶訪問應用系統,無論是應用系統1仍是應用系統2,若是應用系統木有用戶的cookie,那麼用戶會被當前的應用系統重定向到認整系統網站,有兩種狀況:

  第一種:若是這個時候認證系統木有用戶的cookie,那麼就會展現登陸界面給用戶,讓用戶輸入帳號和密碼進行認證,認證成功後會設置用戶cookie,而後將用戶重定向到了原來的應用系統,同時攜帶了用戶cookie給應用系統,當請求再次來到的時候,應用系統發現請求由認證系統重定向過來的,這個時候就會找到了用戶的cookie,併爲本身設置用戶cookie,這個時候應用系統知道了用戶已經登陸(認證)過了,而後就展現相應的頁面給用戶。

  第二種:若是這個時候認證系統有用戶的cookie的話,表明用戶以前已經登陸(認證)過了,認證系統就會將用戶重定向到了原來的應用系統,同時攜帶了用戶cookie給應用系統,當請求再次來到的時候,應用系統發現請求由認證系統重定向過來的,這個時候就會找到了用戶的cookie,併爲本身設置用戶cookie,這個時候應用系統知道了用戶已經登陸(認證)過了,而後就展現相應的頁面給用戶。

下面是我使用tornadao在linux模擬了一下統一驗證,代碼風格略差,勿噴!僅供參考。

# -*- coding: utf-8 -*-

# my ip is 172.18.43.233
# hosts
# 172.18.43.223    www.auth.my.com
# 172.18.43.223    www.a1.my.com
# 172.18.43.223    www.a2.my.com
# ports
# ww.auth.my.com -> 8000
# www.a1.my.com  -> 8010
# www.a2.my.com  -> 8020
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.options
import os.path
import base64
import urllib

from tornado.options import define, options
from urllib import urlencode
define("port", default=8000, help="run on the given port", type=int)

# def get_login_url(self):
#     """Override to customize the login URL based on the request.

#     By default, we use the ``login_url`` application setting.
#     """
#     print self.get_argument
#     self.require_setting("login_url", "@tornado.web.authenticated")
#     return self.application.settings["login_url"]

class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        return self.get_cookie("username")

class LoginHandler(BaseHandler):
    def get(self):
        if not self.get_argument("ticket", None):
            if not self.get_argument("refer", None):
                currentPort = options.port
                if self.get_cookie("username"):
                    self.redirect("/")
                elif currentPort == 8000:
                    self.render('login.html')
                elif currentPort == 8010:
                    refer = urllib.quote('http://www.a1.my.com/')
                    self.redirect("http://www.auth.my.com/login?refer=" + refer)
                elif currentPort == 8020:
                    refer = urllib.quote('http://www.a2.my.com/')
                    self.redirect("http://www.auth.my.com/login?refer=" + refer)
                else:
                    raise HTTPError(403)
            else:
                if self.get_current_user():
                    refer = self.get_argument("refer")
                    ticket = base64.urlsafe_b64encode(self.current_user)
                    self.redirect(refer + "login?ticket=" + ticket)
                else:
                    self.render("login.html")
        else:
            ticket = base64.urlsafe_b64decode(str(self.get_argument("ticket")))
            self.set_cookie("username", ticket)
            self.redirect("/")

    def post(self):
        self.set_cookie("username", self.get_argument("username"))
        if not self.get_argument("refer", None):
            self.redirect("/")
        else:
            refer = self.get_argument("refer")
            ticket = base64.urlsafe_b64encode(self.current_user)
            self.redirect(refer + "login?ticket=" + ticket)

class WelcomeHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        self.render('index.html', user=self.current_user)
            

class LogoutHandler(BaseHandler):
    def get(self):
        self.clear_cookie("username")
        if self.get_argument("auth", None):
            self.redirect("/")
        else:
            self.redirect("http://www.auth.my.com/logout?auth=yes")

if __name__ == "__main__":
    tornado.options.parse_command_line()

    settings = {
        "template_path": os.path.join(os.path.dirname(__file__), "templates"),
        "login_url": "/login"
    }

    application = tornado.web.Application([
        (r'/', WelcomeHandler),
        (r'/login', LoginHandler),
        (r'/logout', LogoutHandler)
    ], **settings)

    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
相關文章
相關標籤/搜索