SSO單點登陸學習總結(2)——基於Cookie+fliter單點登陸實例

一、使用Cookie解決單點登陸

       技術點:html

       一、設置Cookie的路徑爲setPath("/").即Tomcat的目錄下都有效java

       二、設置Cookie的域setDomain(".itcast.com");即bbs.itcast.com,或是mail.itcast.com有效。即跨域。web

       三、設置Cookie的時間。即便用戶不選擇在幾天內自動登陸,也應該保存Cookie以保存在當前瀏覽器沒有關閉的狀況下有效。跨域

       四、使用Filter自動登陸。瀏覽器


實現步驟tomcat

1:首先要準備出幾個虛擬主機並配置hosts文件,即本機DNS修改本機的C:\Windows\System32\drivers\etc下的hosts文件。安全


[html]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. <span style="font-size:18px;"><span style="font-size:18px;"># localhost name resolution is handled within DNS itself.  
  2. #   127.0.0.1        localhost  
  3. #   ::1             localhost  
  4.   
  5. 127.0.0.1       localhost  
  6. 127.0.0.1       www.bbs.itcast.cn  
  7. 127.0.0.1       www.news.itcast.cn  
  8. 127.0.0.1       www.news.com  
  9. 127.0.0.1       www.bbs.com  
  10. 127.0.0.1       www.server.com  
  11. </span></span>  

增長几個Host節點,經過Cookie實現自動登陸,必須配置的虛擬主頁知足xxx.itcast.cn,即主域名必須保持一致。服務器


通常web應用中通常部署在web.xml文件中,單點退出相關配置以下:
cookie

[java]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. <span style="font-size:18px;"><span style="font-size:18px;"><filter>  
  2.         <filter-name>CAS Authentication Filter</filter-name>  
  3.         <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>  
  4.         <init-param>  
  5.         <!--到哪去登陸-->  
  6.             <param-name>casServerLoginUrl</param-name>  
  7.             <param-value>http://www.server.com:8080/login</param-value>  
  8.         </init-param>  
  9.         <init-param>  
  10.         <!--我是誰-->  
  11.             <param-name>serverName</param-name>  
  12.             <param-value>http://www.bbs.com:8080</param-value>  
  13.         </init-param>  
  14.         <init-param>  
  15.             <param-name>renew</param-name>  
  16.             <param-value>false</param-value>  
  17.         </init-param>  
  18.         <init-param>  
  19.             <param-name>gateway</param-name>  
  20.             <param-value>false</param-value>  
  21.         </init-param>  
  22.     </filter>  
  23.       
  24.     <filter>  
  25.         <filter-name>CAS Validation Filter</filter-name>  
  26.         <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>  
  27.         <init-param>  
  28.             <param-name>casServerUrlPrefix</param-name>  
  29.             <param-value>http://www.server.com:8080</param-value>  
  30.         </init-param>  
  31.         <init-param>  
  32.             <param-name>serverName</param-name>  
  33.             <param-value>http://www.bbs.com:8080</param-value>  
  34.         </init-param>  
  35.           
  36.           
  37.         <!--  
  38.         <init-param>  
  39.             <param-name>proxyCallbackUrl</param-name>  
  40.             <param-value>https://localhost:8443/mywebapp/proxyCallback</param-value>  
  41.         </init-param>  
  42.         <init-param>  
  43.             <param-name>proxyReceptorUrl</param-name>  
  44.             <param-value>/mywebapp/proxyCallback</param-value>  
  45.         </init-param>  
  46.         -->  
  47.     </filter>  
  48.       
  49.     <filter>  
  50.         <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
  51.         <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>  
  52.     </filter>  
  53.       
  54.     <filter>  
  55.         <filter-name>CAS Assertion Thread Local Filter</filter-name>  
  56.         <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>  
  57.     </filter>  
  58.   
  59.     <!-- ************************* -->  
  60.   
  61. <!-- Sign out not yet implemented -->  
  62. <!--   
  63.     <filter-mapping>  
  64.         <filter-name>CAS Single Sign Out Filter</filter-name>  
  65.         <url-pattern>/*</url-pattern>  
  66.     </filter-mapping>  
  67. -->  
  68.   
  69.     <filter-mapping>  
  70.         <filter-name>CAS Authentication Filter</filter-name>  
  71.         <url-pattern>/protected/*</url-pattern>  
  72.     </filter-mapping>  
  73.   
  74.     <filter-mapping>  
  75.         <filter-name>CAS Validation Filter</filter-name>  
  76.         <url-pattern>/*</url-pattern>  
  77.     </filter-mapping>  
  78.        
  79.     <filter-mapping>  
  80.         <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
  81.         <url-pattern>/*</url-pattern>  
  82.     </filter-mapping>  
  83.       
  84.     <filter-mapping>  
  85.         <filter-name>CAS Assertion Thread Local Filter</filter-name>  
  86.         <url-pattern>/*</url-pattern>  
  87.     </filter-mapping>  
  88.       
  89.     <filter-mapping>  
  90.         <filter-name>CAS Validation Filter</filter-name>  
  91.         <url-pattern>/proxyCallback</url-pattern>     
  92.     </filter-mapping>  
  93.       
  94.     <!--  *********************** -->  
  95.   
  96. <!-- Sign out not yet implemented -->  
  97. <!--   
  98.     <listener>  
  99.         <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>  
  100.     </listener>  
  101. -->  
  102.   
  103.     <!--  *********************** -->  
  104.   
  105.     <welcome-file-list>  
  106.         <welcome-file>index.jsp</welcome-file>  
  107.     </welcome-file-list></span></span>  

說明:咱們看到單點退出的相關類結構,web.xml配置了單點退出的相關類(1個監聽器SingleSignOutHttpSessionListener,2個過濾器SingleSignOutFilter,SimpleServerLogoutHandler)。session

       

       實現利用了session存儲機制,SessionStoreManager是個單例類,用於管理session的存儲、刪除;SessionMappingStorage是session的存儲、刪除的執行者,能夠看到實際存儲的結構是一個artifactId、sessionId爲名值對的HashMap表;監聽器SingleSignOutHttpSessionListener的做用是session銷燬時,調用session管理單例類SessionStoreManager進行session的刪除銷燬;

        SingleSignOutFilter的做用有2個:一個是在單點訪問攔截安全資源時調用單例類SessionStoreManager存儲session,另外一個是在單點退出時調用單例類SessionStoreManager刪除session;SimpleServerLogoutHandler的做用是將客戶端的退出請求轉發到SSO服務器端,集中處理作各個子系統的單點退出。


二、先在bbs(或是mail)虛擬目錄下,開發一個能夠自動登陸的程序,使用Filter:

[html]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. <span style="font-size:18px;"><span style="font-size:18px;">一、登陸的主頁以下:  
  2. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  3. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>  
  4. <html>  
  5.   <head>  
  6.   </head>  
  7.   <body>  
  8.         <p>在同一臺服務器上,多個站點自動登陸....>>:<%=session.getId()%></p>  
  9.         <c:if test="${empty sessionScope.user}">  
  10.             <form name="f" method="post" action="<c:url value='/login'/>">  
  11.                 Name:<input type="text" name="name"/><br/>  
  12.                 Pwd:<input type="text" name="pwd"/><br/>  
  13.                 <input type="checkbox" name="chk" value="7">一週內自動登陸<br/>  
  14.                 <input type="submit" value="登陸"/>           
  15.             </form>  
  16.         </c:if>  
  17.         <c:if test="${not empty sessionScope.user}">  
  18.             歡迎你:${user}。<a href="<c:url value='/loginout'/>">安全退出</a>  
  19.         </c:if>  
  20.         <br/>  
  21.         相關站點:(只要在一邊登陸成功,便可以自動登陸到另外一個程序)<br/>  
  22.         <a href="http://mail.itcast.com:7777">mail.itcast.com</a><br/>  
  23.         <a href="http://bbs.itcast.com:7777">bbs.itcast.com</a><br/>  
  24.   </body>  
  25. </html>  
  26. </span></span>  

二、登陸的Servlet程序以下:

[java]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. <span style="font-size:18px;"><span style="font-size:18px;">/** 
  2.  * 用戶登陸 
  3.  */  
  4. public class LoginServlet extends HttpServlet{  
  5.     public void doGet(HttpServletRequest req, HttpServletResponse resp)  
  6.             throws ServletException, IOException {  
  7.         doPost(req, resp);  
  8.     }  
  9.     public void doPost(HttpServletRequest req, HttpServletResponse resp)  
  10.             throws ServletException, IOException {  
  11.         String nm = req.getParameter("name");  
  12.         String pwd = req.getParameter("pwd");  
  13.         String chk = req.getParameter("chk");   //是否選中了7天自動登陸  
  14.         String forward = "/index.jsp";  
  15.         if(nm!=null && !nm.trim().equals("") && nm.startsWith("it")//用戶名是it開始,且密碼是pwd開始的能夠登陸  
  16.                 && pwd !=null && !pwd.trim().equals("") &&  
  17.                 pwd.startsWith("pwd")){  
  18.             System.err.println("登陸成功。。。。。");  
  19.             forward = "/jsps/welcome.jsp";  
  20.             //不管如何,都要設置cookie,若是沒有選擇自動登陸,則只在當前頁面的跳轉時有效,不然設置有效期間爲7天。  
  21.             Cookie cookie = new Cookie("autologin",nm+"@"+pwd);  
  22.             cookie.setPath("/");                //若是路徑爲/則爲整個tomcat目錄有用  
  23.             cookie.setDomain(".itcast.com");    //設置對全部*.itcast.com爲後綴的域名效  
  24.             if(chk!=null){  
  25.                 int time = 1*60*60*24*7;    //1秒*60=1分*60分=1小時*24=1天*7=7天  
  26.                 cookie.setMaxAge(time);  
  27.             }  
  28.             resp.addCookie(cookie);  
  29.             req.getSession().setAttribute("user", nm);  
  30.         }else{  
  31.             System.err.println("登陸不成功。。。。。。");  
  32.         }  
  33.         req.getRequestDispatcher(forward).forward(req, resp);  
  34.     }  
  35. }  
  36.   
  37. </span></span>  

三、自動登陸的Filter程序以下:

[java]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. <span style="font-size:18px;"><span style="font-size:18px;">/** 
  2.  * 自動登陸 
  3.  */  
  4. public class AutoLogin implements Filter {  
  5.     public void destroy() {}  
  6.     public void doFilter(ServletRequest req, ServletResponse resp,  
  7.             FilterChain chain) throws IOException, ServletException {  
  8.         System.err.println("開始自動登陸驗證.....");//此類中應該對登陸的servlet直接放行。根據判斷url決定。  
  9.         HttpServletRequest requ = (HttpServletRequest) req;  
  10.         HttpSession s = requ.getSession();  
  11.         if (s.getAttribute("user") != null) {//若是用戶已經登陸則直接放行  
  12.             System.err.println("用戶已經登陸,沒有必需要再作自動登陸。。。。");  
  13.         } else {  
  14.             Cookie[] cookies = requ.getCookies();  
  15.             if (cookies != null) {  
  16.                 for (Cookie ck : cookies) {  
  17.                     if (ck.getName().equals("autologin")) {// 是不是自動登陸。。。。  
  18.                         System.err.println("自動登陸成功。。。。。");  
  19.                         String val = ck.getValue();  
  20.                         String[] vals = val.split("@");  
  21.                         s.setAttribute("user", vals[0]);  
  22.                     }  
  23.                 }  
  24.             }  
  25.         }  
  26.         chain.doFilter(req, resp);  
  27.     }  
  28.     public void init(FilterConfig filterConfig) throws ServletException {}  
  29. }  
  30. </span></span>  


四、正常退出的Servlet以下

[java]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. <span style="font-size:18px;"><span style="font-size:18px;">/** 
  2.  * 安全退出刪除Cookie 
  3.  */  
  4. public class LoginOutServlet extends HttpServlet {  
  5.     public void doGet(HttpServletRequest req, HttpServletResponse resp)  
  6.             throws ServletException, IOException {  
  7.         HttpSession s = req.getSession();       //獲取Session  
  8.         Cookie cookie = new Cookie("autologin","");//必須聲明一個徹底相同名稱的Cookie  
  9.         cookie.setPath("/");//路徑也要徹底相同  
  10.         cookie.setDomain(".itcast.com");//域也要徹底相同  
  11.         cookie.setMaxAge(0);//設置時間爲0,以直接刪除Cookie  
  12.         resp.addCookie(cookie);  
  13.         s.removeAttribute("user");  
  14.         System.err.println("安全退出。。。。。");  
  15.         resp.sendRedirect(req.getContextPath()+"/index.jsp");  
  16.     }  
  17. }  
  18. </span></span>  

這種是基於最簡單的方式實現的單點登陸

相關文章
相關標籤/搜索