• SSO单点登录入门


    1,SSO简介

          SSO(Single Sign-On,单点登录)是身份管理中的一部分。SSO 的一种较为通俗的定义是:SSO 是指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过一个应用中的安全验证后,再访问其他应用中的受保护资源时,不再需要重新登录验证。

    SSO与身份管理软件背景

           目前的企业应用环境中,往往有很多的应用系统,如办公自动化(OA)系统,财务管理系统,档案管理系统,信息查询系统等等。这些应用系统服务于企业的信息化建设,为企业带来了很好的效益。但是,用户在使用这些应用系统时,并不方便。用户每次使用系统,都必须输入用户名称和用户密码,进行身份验证;而且,应用系统不同,用户账号就不同,用户必须同时牢记多套用户名称和用户密码。特别是对于应用系统数目较多,用户数目也很多的企业,这个问题尤为突出。问题的原因并不是系统开发出现失误,而是缺少整体规划,缺乏统一的用户登录平台。

     

    SSO 基于Cookie+fliter实现单点登录 实例解析(一)

     

    目录(?)[+]

     

    接上文,SSO的理论讲解,接下来实践实践!

    1、使用Cookie解决单点登录

           技术点:

           1、设置Cookie的路径为setPath("/").即Tomcat的目录下都有效

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

           3、设置Cookie的时间。即使用户不选择在几天内自动登录,也应该保存Cookie以保存在当前浏览器没有关闭的情况下有效。

           4、使用Filter自动登录。

    实现步骤

    1:首先要准备出几个虚拟主机并配置hosts文件,即本机DNS修改本机的C:WindowsSystem32driversetc下的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文件中,单点退出相关配置如下:

    [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存储机制,SessionStoreManager是个单例类,用于管理session的存储、删除;SessionMappingStorage是session的存储、删除的执行者,可以看到实际存储的结构是一个artifactId、sessionId为名值对的HashMap表;监听器SingleSignOutHttpSessionListener的作用是session销毁时,调用session管理单例类SessionStoreManager进行session的删除销毁;

            SingleSignOutFilter的作用有2个:一个是在单点访问拦截安全资源时调用单例类SessionStoreManager存储session,另一个是在单点退出时调用单例类SessionStoreManager删除session;SimpleServerLogoutHandler的作用是将客户端的退出请求转发到SSO服务器端,集中处理做各个子系统的单点退出。

    2、先在bbs(或是mail)虚拟目录下,开发一个可以自动登录的程序,使用Filter:

    [html] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. <span style="font-size:18px;"><span style="font-size:18px;">1、登录的主页如下:  
    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}。<href="<c:url value='/loginout'/>">安全退出</a>  
    19.         </c:if>  
    20.         <br/>  
    21.         相关站点:(只要在一边登录成功,即可以自动登录到另一个程序)<br/>  
    22.         <href="http://mail.itcast.com:7777">mail.itcast.com</a><br/>  
    23.         <href="http://bbs.itcast.com:7777">bbs.itcast.com</a><br/>  
    24.   </body>  
    25. </html>  
    26. </span></span>  

    2、登录的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>  

    3、自动登录的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>  


    4、正常退出的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>  

    这种是基于最简单的方式实现的单点登录,效果图在下篇博客中的

    使用基于CAS单点登录流程实例与效果图

     

    下下篇

    基于使用Shiro 和使用spring security控制权限的方案

     
     
  • 相关阅读:
    (五)《Java编程思想》——final关键字
    eclipse与github建立版本关联、git使用说明
    (四)《Java编程思想》——可变参数列表
    (三)《Java编程思想》——构造函数初始化
    (二)《Java编程思想》——t h i s 关键字
    (一)《Java编程思想》学习——按位运算符、移位运算符
    (三)一个工作任务引起的乱战——udp通信
    (二)一个工作任务引起的乱战——C++程序编译为dll,让C#调用
    (一)一个工作任务引起的乱战——c#中结构体与byte[]间相互转换
    如何反编译silverlight
  • 原文地址:https://www.cnblogs.com/Feiyang-Lafe/p/6107616.html
Copyright © 2020-2023  润新知