什麼是單點登陸:大白話就是多個網站共享一個用戶名和密碼的技術,對於普通用戶來講,只須要登陸其中任意一個網站,登陸其餘網站的時候就可以自動登錄,不須要再輸入java
用戶名和密碼了。git
單點登陸類型:github
1.具備相同一級域名的多個網站,以新浪爲例,新浪首頁其實是一個導航頁面,它提供了不少不少的旗下網站地址,好比web
(1)新浪新聞: http://news.sina.com.cn/瀏覽器
(2)新浪科技:http://tech.sina.com.cn/tomcat
(3)新浪博客:http://blog.sina.com.cn/服務器
等等,它們都有相同的一級域名.sina.com.cncookie
使用Cookie將登錄信息寫到本地,域名指定爲.sina.com.cn,那麼在訪問新浪博客http://blog.sina.com.cn/的時候就會帶有登錄信息,使用過濾器便可實現自動登錄。session
2.沒有相同域名的多個網站,好比淘寶和天貓
(1)淘寶:https://www.taobao.com/
(2)天貓:https://www.tmall.com/
雖然是兩個不一樣的網站,並且沒有相同的域名,可是在登錄淘寶以後,再訪問天貓頁面就會自動登錄,這種實現的技術就不只僅是1.中具備相同一級域名的時候那麼簡單了。在java中,使用CAS技術解決這種狀況比較常見。
1、使用過濾器和Cookie技術具備相同一級域名的多個網站實現單點登陸
項目練習地址:https://github.com/kdyzm/day68_SSO
1.在Tomcat中配置多個站點的方法
(1)首先修改C:\Windows\System32\drivers\etc\hosts配置文件
添加的內容以下:
#有相同的一級域名的單點登陸測試 127.0.0.1 www.bbs.kdyzm.com 127.0.0.1 www.news.kdyzm.com
(2)修改%Tomcat_Home%/conf/server.xml配置文件,在<Host></Host>標籤後面添加下面的配置:
<!--有相同一級域名的單點登陸測試--> </Host> <Host name="www.news.kdyzm.com" appBase="news"> </Host> <Host name="www.bbs.kdyzm.com" appBase="bbs"> </Host>
(3)上面的appBase指的是%Tomcat_Home%路徑下的文件夾,因此建立兩個同名的文件夾(news、bbs)分別對應appBase中的內容,這兩個文件夾和webapps文件夾同級。
這樣就有了三個站點,分別是bbs、news、webapps
2.新建Jsp文件,使用jsp語法進行判斷是否已經登錄,針對是否已經登陸顯示不一樣的內容:已經登錄的顯示歡迎話語;沒有登錄過的顯示登陸表單。
/index.jsp內容以下:
1 <body> 2 <c:choose> 3 <c:when test="${not empty sessionScope.user}"> 4 歡迎你,${sessionScope.user.userName} 5 </c:when> 6 <c:otherwise> 7 <form method="post" 8 action="${pageContext.servletContext.contextPath}/loginServlet"> 9 <table> 10 <tr> 11 <td>用戶名</td> 12 <td><input type="text" name="userName"></td> 13 </tr> 14 <tr> 15 <td>密碼</td> 16 <td><input type="text" name="password"></td> 17 </tr> 18 <tr> 19 <td><input type="submit" value="登錄"></td> 20 <td><input type="reset" value="重置"></td> 21 </tr> 22 </table> 23 </form> 24 </c:otherwise> 25 </c:choose> 26 </body>
3.書寫Servlet類
/loginServlet 中的內容以下
1 package com.kdyzm.servlet; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.Cookie; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 import com.kdyzm.domain.User; 12 13 public class LoginServlet extends HttpServlet { 14 private static final long serialVersionUID = -7472135565931819576L; 15 @Override 16 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 17 throws ServletException, IOException { 18 this.doPost(req, resp); 19 } 20 @Override 21 protected void doPost(HttpServletRequest request, HttpServletResponse response) 22 throws ServletException, IOException { 23 request.setCharacterEncoding("utf-8"); 24 response.setContentType("text/html;charset=utf-8"); 25 26 String userName=request.getParameter("userName"); 27 String password=request.getParameter("password"); 28 if(userName.equals(password)){ 29 User user=new User(); 30 user.setUserName(userName); 31 user.setPassword(password); 32 //保存到Session 33 request.getSession().setAttribute("user", user); 34 //保存到Cookie 35 Cookie cookie=new Cookie("userName",user.getUserName()); 36 cookie.setMaxAge(3600); //設置生命週期爲一個小時 37 cookie.setDomain(".kdyzm.com"); //設置域名 38 cookie.setPath("/"); //設置路徑爲根路徑 39 response.addCookie(cookie); 40 } 41 response.sendRedirect(request.getContextPath()+"/index.jsp"); 42 } 43 }
到此爲止已經實現了登錄的功能,而且將內容寫入到了Cookie和Session中。
下一步實現自動登陸功能,這時候就須要一個過濾器進行判斷請求的信息中是否帶有登陸信息。
4.AutoLoginFilter過濾器的書寫以下:
1 package com.kdyzm.filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest; 10 import javax.servlet.ServletResponse; 11 import javax.servlet.http.Cookie; 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 import javax.servlet.http.HttpSession; 15 16 import com.kdyzm.domain.User; 17 18 /** 19 * 不作登陸驗證,只作自動登陸 20 * @author kdyzm 21 * 22 */ 23 public class AutoLoginFilter implements Filter{ 24 25 @Override 26 public void init(FilterConfig filterConfig) throws ServletException { 27 System.out.println("過濾器初始化!"); 28 } 29 30 @Override 31 public void doFilter(ServletRequest req, ServletResponse resp, 32 FilterChain chain) throws IOException, ServletException { 33 HttpServletRequest request=(HttpServletRequest) req; 34 HttpServletResponse response=(HttpServletResponse) resp; 35 HttpSession session=request.getSession(); 36 System.out.println("被攔截器過濾!"); 37 //先判斷是否已經登錄再作其餘的判斷比較高效 38 if(session.getAttribute("user")==null){ 39 System.out.println("尚未登錄!"); 40 Cookie [] cookies=request.getCookies(); 41 if(cookies!=null){ 42 for(Cookie cookie:cookies){ 43 String name=cookie.getName(); 44 if(name.equals("userName")){ 45 System.out.println("尚未登陸,可是存在登陸信息!"); 46 User user=new User(); 47 String userName=cookie.getValue(); 48 String password=userName; 49 user.setUserName(userName); 50 user.setPassword(password); 51 session.setAttribute("user", user); 52 } 53 System.out.println(cookie.getName()+":"+cookie.getValue()); 54 } 55 } 56 } 57 chain.doFilter(request, response); 58 } 59 60 @Override 61 public void destroy() { 62 System.out.println("過濾器被銷燬!"); 63 } 64 65 }
到此,準備工做已經完成,下一步進行部署工做。
5.在新創建的兩個站點下分別新建ROOT文件夾,而且將MyEclipse項目中Webroot下的全部文件拷貝過去
爲何要新建ROOT文件夾?tomcat服務器默認訪問站點下的ROOT文件夾中的內容,使用ROOT文件夾訪問的時候就不須要加上項目名稱了。
6.分別修改兩個站點下的index.jsp頁面,目的是在測試的時候方便區分。
好比在bbs站點下的index.jsp頁面中的修改內容:
<c:choose> <c:when test="${not empty sessionScope.user}"> 歡迎你,${sessionScope.user.userName}<br/> 這裏是論壇界面! </c:when>
在news站點下的修改內容
<c:choose> <c:when test="${not empty sessionScope.user}"> 歡迎你,${sessionScope.user.userName}<br/> 這裏是新聞界面! </c:when>
7.啓動tomcat,進行測試,這裏使用火狐瀏覽器進行測試
首先,訪問http://localhost/day68_SSO/,輸入英文用戶名和密碼,二者保證是相同的字符串。以xiaozhang爲例:
查看Cookie信息,發現並無指望中的.kdyzm.com的cookie信息,這是由於咱們訪問的是localhost:
接着訪問www.bbs.kdyzm.com,出現的頁面和以前如出一轍,此次咱們輸入bbs爲登陸名和密碼:
查看cookie信息,發現多了兩種cookie信息,這時候,.kdyzm.com域中的cookie已經寫成功了,並且其生命週期爲一個小時、域爲.kdyzm.com、名稱爲userName、內容爲bbs這些內容都和程序設計的預期徹底相同;同時bbs.kdyzm.com中也有了新的cookie信息,這個信息只是自動分配的JSESSIONID信息:
最後登陸www.news.kdyzm.com,發現已經自動登錄了:
查看Cookie信息,發現多了news.kdyzm.com的站點信息的Cookie,可是並非登錄信息的Cookie,只是JSESSIONID而已,它發送的Cookie信息是從kdyzm.com域名中獲取到的。
2、沒有相同的一級域名的實現多個站點的單點登陸的方法:CAS
1.使用CAS框架實現多個站點若是沒有相同的一級域名的單點登陸測試
(1)CAS:Central Authentication Service,翻譯過來就是中心認證服務,顧名思義,該框架的功能就是「認證」
使用CAS框架實現多個不一樣站點的單點登陸的原理的關鍵就是使用一個認證服務器集中處理登錄的事宜。
流程圖以下圖所示:
(2)使用CAS完成不一樣站點的單點登陸的demo下載地址:
https://github.com/kdyzm/day68_SSO_CAS_Demo
2.運行demo測試的步驟
1).首先須要修改hosts配置文件:添加上一下的兩行信息:
127.0.0.1 www.bbs.com 127.0.0.1 www.news.com
2).修改hosts文件,添加一下的三行信息
<Host name="www.server.com" appBase="server">
</Host>
<Host name="www.news.com" appBase="news1">
</Host>
<Host name="www.bbs.com" appBase="bbs1">
</Host>
3).將news1文件夾和bbs1文件夾分別拷貝到%Tomcat_Home%文件夾中,分別做爲兩個獨立的站點;將server文件夾拷貝到%Tomcat_Home%文件夾中,做爲認證服務器站點。
4).啓動tomcat服務器。首先訪問www.server.com,若是沒有任何問題的話,才能進行下一步。出現的界面以下:
5).隨便輸入一個用戶名,可是必須確保密碼和用戶名相同,這是服務端默認的一個認證規則。若是成功了,則會顯示以下界面:
清空瀏覽器cookies信息,而後進行下一步。
6).訪問www.bbs.com,單擊下圖中的「to to protected area」超連接,在顯示出來的頁面中輸如bbs做爲用戶名,使用bbs做爲密碼登錄
注意上圖中的地址欄部分,已經不是www.bbs.com站點了,而是www.server.com。
登錄成功:
7).訪問www.news.com,直接單擊"go to protected area",發現已經自動登錄了。
3.演示到此結束,進行該測試的時候必須使用MyEclipse啓動tomcat服務器;若是隻是單獨使用tomcat則頗有可能會沒法訪問www.server.com。
4.具體使用方法比較複雜,可是這種技術在真正的開發中可能用不着。暫時存檔。