1.什麼是單點登入
所謂單點登入,你可以簡單的理解為有兩個網站,這個兩個網站的域名是不相同,但是它們同屬於一家公司。當你在某一個網站登入輸入完密碼之後,你再去訪問第二個網站時,就不需要再次輸入密碼了,可以直接顯示登入狀態。例如你在百度文庫登入之後,再去百度知道,你發現也同樣處於登入狀態。
2.單點登入原理單點登入最重要的是認證中心,假設有a網站和b網站,當你登入其中任何一個時,都會跳轉到認證中心,實際的使用者名稱和密碼的驗證是在這裡完成的。
2.1認證中心如何區分子系統登入時,都跳轉到認證中心,那麼認證中心怎麼區分這次請求是從哪個網站來的呢?方法很簡單,你登入a網站時,a網站的後臺跳轉到認證中心時,會將自己網站的網址作為引數(referer),這樣,認證中心就知道是哪個子系統網站在登入了。
2.2認證中心登入後做什麼你在認證中心填寫好使用者名稱和密碼登入後,認證中心會再次跳轉到a網站,而且要帶上一個ticket,這個很關鍵,同時設定session
2.3 a網站怎麼辦對於a網站,請求裡帶有ticket,那麼就對這個ticket進行驗證,看他是不是認證中心頒發的(我的程式沒有做這個驗證),如果是呢,則登入成功
2.4 b網站如何登入a網站登入後,你又想去b網站逛逛,和a網站一樣,也要跳轉到認證中心,可是不同於第一次跳轉,在2.2中,已經設定了session,就說明已經在認證中心認證過了,所以認證中心這次會直接跳轉到b網站,也帶著ticket,b網站看到ticket,也去驗證是否是認證中心頒發的,最後b網站成功登入。
3 程式碼構建專案結構如下所示,專案使用的框架是python flask。
3.1 login.html<!DOCTYPE html> <html><head> <meta charset="utf-8"> <title>SSO</title> <meta name="author" content="" /> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <meta name="keywords" content="SSO" /> <meta name="description" content="SSO" /></head><body><form method="POST" action="dologin?referer={{ referer }}"> account: <input type="username" name="username"><br>password: <input type="password" name="password"><br> <input type="submit" value="logon"></body></html>
3.2 sso.py#coding: utf8 import osfrom datetime import timedeltafrom flask import Flask, session, render_template, request, redirectimport urllib app = Flask(__name__) app.secret_key = '123456'app.permanent_session_lifetime = timedelta(seconds=30 * 24 * 60 * 60) @app.route('/login')def login(): session.permanent = True referer = request.args.get('referer', None) if referer is not None: referer = referer.strip() if 'name' in session: if referer is not None: return redirect(referer + '?ticket=' + _makeTicket()) return render_template('login.html', **dict(referer=referer)) @app.route('/dologin',methods=['POST'])def doLogin(): ''' 這裡沒有真正的去進行驗證,直接寫session了,然後redirect了 ''' session.permanent = True print request.args print request.form referer = request.args.get('referer', None) if(request.form.get('username')== 'zhangsan') and (request.form.get('password')=='111111'): print "username and password is right" else: return "username and passwprd is not right" if referer is not None: referer = urllib.unquote(referer.strip()) #不實現登入功能,直接設定登入態 _setLoginState() if referer: return redirect(referer + '?ticket=' + _makeTicket()) else: return 'error' def _setLoginState(): session['name'] = 'zhangsan' def _makeTicket(): '''生成ticket,這裡只是簡單返回使用者名稱,真實場景中可以使用des之類的加密演算法''' return 'zhangsan' if __name__ == '__main__': app.run( host="0.0.0.0", port=int("5200"), debug=True )
3.3 a.py#coding: utf8 import osfrom datetime import timedeltafrom flask import Flask, session, redirect, url_for, requestimport urllib app = Flask(__name__) app.secret_key = 'b123456'app.permanent_session_lifetime = timedelta(seconds=24 * 60 * 60) @app.route('/')def index(): #表示存活期為瀏覽器程序的存活期 session.permanent = False ticket = request.args.get('ticket', None) #此處應該驗證ticket是認證中心釋出的 if ticket is not None: session['name'] = ticket.strip() #檢測登入態 if 'name' in session: return 'a登入成功' else: referer = urllib.quote('http://www.a.com:5201/') return redirect('http://www.sso.com:5200/login?referer=' + referer) if __name__ == '__main__': app.run( host="0.0.0.0", port=int("5201"), debug=True )
3.4 b.py#coding: utf8 import osfrom datetime import timedeltafrom flask import Flask, session, redirect, url_for, requestimport urllib app = Flask(__name__) app.secret_key = 'a123456'app.permanent_session_lifetime = timedelta(seconds=24 * 60 * 60) @app.route('/')def index(): #表示存活期為瀏覽器程序的存活期 session.permanent = False ticket = request.args.get('ticket', None) print session if ticket is not None: session['name'] = ticket.strip() #檢測登入態 if 'name' in session: print session['name'] return 'b登入成功' else: referer = urllib.quote('http://www.b.com:5202/') return redirect('http://www.sso.com:5200/login?referer=' + referer) if __name__ == '__main__': app.run( host="0.0.0.0", port=5202, debug=True)
注意:程式碼構建完成之後需要在window的hosts檔案或者伺服器的hosts檔案中新增域名和ip的對映。
4.結果演示首先在瀏覽器中輸入http://www.a.com:5201,可以看到自動跳轉到了http://www.sso.com:5200,並且呼叫了login介面
這個時候輸入賬號密碼zhangsan/111111,會發現呼叫了dologin介面,並且帶上了a網站的域名作為引數,驗證通過後重新跳轉到了www.a.com網站,並帶上了ticket引數,並且顯示了a網站登入成功的結果。
這個時候再去登入www.b.com,會發現,會先去www.sso.com認證一下,發現session已經存在之後,就會跳回www.b.com,並且設定session。所以在沒有輸入密碼的情況下,b網站也成功登入。