寫博客的原因:太晚了,而舍友的呼嚕聲驚天動地,無法入睡。
環境:tornado,linux(linux mint 類ubuntu),nginx, python2.7
首先是講一下nginx搭建多台虛擬主機的過程,大致的步驟如下:
這里我配置了三個網站他們分別是:
#new host for distribute course experience
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)
172.18.43.223為我的電腦在互聯網上的ip地址,你可以通過在終端下執行ifconfig命令查看你當前的電腦的ip地址
同時需要將這些網站的配置信息添加到/etc/hosts文件中,如圖:
至於/ect/hosts文件是干什么用的,可以看這里
- 在nginx(ubuntu下為/etc/nginx.conf)的配置文件里面配置多台虛擬主機(server),形如:
server {
配置信息
}
里面server_name項就是你要在瀏覽器輸入的網址,proxy_pass為你指定哪個upstream給這台虛擬主機,這里為frontends - 然后就是配置真正能夠提供服務的地方了,那就是配置upstream了,其配置如下:
前面的www.auth.my.com代理的upstream就是frontends里面的127.0.0.1:8000(真正提供服務的網站)了
總結一下,先是訪問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()