什么是单点登陆:大白话就是多个网站共享一个用户名和密码的技术,对于普通用户来讲,只须要登陆其中任意一个网站,登陆其余网站的时候就可以自动登录,不须要再输入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.具体使用方法比较复杂,可是这种技术在真正的开发中可能用不着。暂时存档。