单点登录:SSO(Single Sign On)

  什么是单点登录:大白话就是多个网站共享一个用户名和密码的技术,对于普通用户来说,只需要登录其中任意一个网站,登录其他网站的时候就能够自动登陆,不需要再输入

用户名和密码了。

  单点登录类型:

    1.具有相同一级域名的多个网站,以新浪为例,新浪首页实际上是一个导航页面,它提供了很多很多的旗下网站地址,比如

      (1)新浪新闻: http://news.sina.com.cn/

      (2)新浪科技:http://tech.sina.com.cn/

      (3)新浪博客:http://blog.sina.com.cn/

        等等,它们都有相同的一级域名.sina.com.cn

        使用Cookie将登陆信息写到本地,域名指定为.sina.com.cn,那么在访问新浪博客http://blog.sina.com.cn/的时候就会带有登陆信息,使用过滤器即可实现自动登陆。

    2.没有相同域名的多个网站,比如淘宝和天猫

      (1)淘宝:https://www.taobao.com/

      (2)天猫:https://www.tmall.com/

      虽然是两个不同的网站,而且没有相同的域名,但是在登陆淘宝之后,再访问天猫页面就会自动登陆,这种实现的技术就不仅仅是1.中具有相同一级域名的时候那么简单了。在java中,使用CAS技术解决这种情况比较常见。

一、使用过滤器和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内容如下:

 <body>
<c:choose>
<c:when test="${not empty sessionScope.user}">
欢迎你,${sessionScope.user.userName}
</c:when>
<c:otherwise>
<form method="post"
action="${pageContext.servletContext.contextPath}/loginServlet">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="userName"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td><input type="submit" value="登陆"></td>
<td><input type="reset" value="重置"></td>
</tr>
</table>
</form>
</c:otherwise>
</c:choose>
</body>

  3.书写Servlet类

  /loginServlet 中的内容如下

 package com.kdyzm.servlet;

 import java.io.IOException;

 import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.kdyzm.domain.User; public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = -7472135565931819576L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8"); String userName=request.getParameter("userName");
String password=request.getParameter("password");
if(userName.equals(password)){
User user=new User();
user.setUserName(userName);
user.setPassword(password);
//保存到Session
request.getSession().setAttribute("user", user);
//保存到Cookie
Cookie cookie=new Cookie("userName",user.getUserName());
cookie.setMaxAge(3600); //设置生命周期为一个小时
cookie.setDomain(".kdyzm.com"); //设置域名
cookie.setPath("/"); //设置路径为根路径
response.addCookie(cookie);
}
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
}

  到此为止已经实现了登陆的功能,并且将内容写入到了Cookie和Session中。

  下一步实现自动登录功能,这时候就需要一个过滤器进行判断请求的信息中是否带有登录信息。

  4.AutoLoginFilter过滤器的书写如下:

 package com.kdyzm.filter;

 import java.io.IOException;

 import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import com.kdyzm.domain.User; /**
* 不做登录验证,只做自动登录
* @author kdyzm
*
*/
public class AutoLoginFilter implements Filter{ @Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器初始化!");
} @Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest) req;
HttpServletResponse response=(HttpServletResponse) resp;
HttpSession session=request.getSession();
System.out.println("被拦截器过滤!");
//先判断是否已经登陆再做其他的判断比较高效
if(session.getAttribute("user")==null){
System.out.println("还没有登陆!");
Cookie [] cookies=request.getCookies();
if(cookies!=null){
for(Cookie cookie:cookies){
String name=cookie.getName();
if(name.equals("userName")){
System.out.println("还没有登录,但是存在登录信息!");
User user=new User();
String userName=cookie.getValue();
String password=userName;
user.setUserName(userName);
user.setPassword(password);
session.setAttribute("user", user);
}
System.out.println(cookie.getName()+":"+cookie.getValue());
}
}
}
chain.doFilter(request, response);
} @Override
public void destroy() {
System.out.println("过滤器被销毁!");
} }

  到此,准备工作已经完成,下一步进行部署工作。

  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域名中获取到的。

    

二、没有相同的一级域名的实现多个站点的单点登录的方法: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.具体使用方法比较复杂,但是这种技术在真正的开发中可能用不着。暂时存档。

【Java EE 学习 68】【单点登录】【两种单点登录类型:SSO/CAS、相同一级域名的SSO】的更多相关文章

  1. 【Java EE 学习 35 上】【strus2】【类型转换器】【struts2和Servlet API解耦】【国际化问题】【资源文件乱码问题已经解决】

    一.类型转换器 1.在动作类action中,声明和表单中name属性的值同名的属性,提供get和set方法,struts2就可以通过反射机制,从页面中获取对应的内容 package com.kdyzm ...

  2. Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库

    参考: https://my.oschina.net/gaussik/blog/513444 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 ...

  3. 【Java EE 学习 80 上】【WebService】

    一.WebService概述 什么是WebService,顾名思义,就是基于Web的服务,它使用Http方式接收和响应外部系统的某种请求,从而实现远程调用.WebService实际上就是依据某些标准, ...

  4. Java EE 学习(8):IDEA + maven + spring 搭建 web(4)- 用户管理

    转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) ava E ...

  5. Java EE 学习(5):IDEA + maven + spring 搭建 web(1)

    参考:http://www.cnblogs.com/lonelyxmas/p/5397422.html http://www.ctolib.com/docs-IntelliJ-IDEA-c--1590 ...

  6. Java EE学习——Quartz的Cron表达式

    经历过低谷后,还是要好好学习,越失落会越来越落后. 今天写一下Cron表达式的用法,虽然是之前自己写的,也过了挺长一段时间,这次就拿出来作为回顾吧. Cron表达式是Quartz的精髓(个人觉得),比 ...

  7. Java EE 学习(6):IDEA + maven + spring 搭建 web(2)- 配置 Spring

    参考:https://my.oschina.net/gaussik/blog/513353 注:此文承接上一文:Java EE 学习(5):IDEA + maven + spring 搭建 web(1 ...

  8. 【Java EE 学习 30】【闪回】【导入导出】【管理用户安全】【分布式数据库】【数据字典】【方案】

    一.闪回 1.可能的误操作 (1)错误的删除了记录 (2)错误的删除了表 (3)查询历史记录 (4)撤销已经提交了的事务. 2.对应着以上四种类型的误操作,有四种闪回类型 (1)闪回表:将表回退到过去 ...

  9. Java中的ReentrantLock和synchronized两种锁定机制的对比

    问题:多个访问线程将需要写入到文件中的数据先保存到一个队列里面,然后由专门的 写出线程负责从队列中取出数据并写入到文件中. http://blog.csdn.net/top_code/article/ ...

随机推荐

  1. webView和js交互

    与 js 交互 OC 调用 JS // 执行 js - (void)webViewDidFinishLoad:(UIWebView *)webView { NSString *title = [web ...

  2. jquery隐藏侧边栏和折叠侧边栏方法

    两种效果如下所示: 隐藏侧边栏: 折叠侧边栏: 下面,分享隐藏侧边栏实现方法: 实现思路:给body切换class,通过class控制侧边栏和主体部分left 来实现效果 html部分: <di ...

  3. CSS样式表

    CSS样式及属性 样式标的基本概念 样式表的分类 1.内联样式表 和html联合显示,控制精确,但可重用性差,冗余多. 例:<p style="font-size:14px;" ...

  4. 阿里云提示Discuz uc.key泄露导致代码注入漏洞uc.php的解决方法

    适用所有用UC整合 阿里云提示漏洞: discuz中的/api/uc.php存在代码写入漏洞,导致黑客可写入恶意代码获取uckey,.......... 漏洞名称:Discuz uc.key泄露导致代 ...

  5. 为何img、input等内联元素可以设置宽、高

    元素是文档结构的基础,在CSS中,每个元素生成了一个包含了元素内容的框(box,也译为“盒子”).但是不同的元素显示的方式会有所不同,例如<div>和<span>就不同,而&l ...

  6. SQL 从指定表筛选指定行信息 获取表行数

    1.获取指定表的行数 --获取表中数据行数 --select max([列名]) from 表名 2.筛选指定表的指定行数据(数据表分页获取) http://www.cnblogs.com/morni ...

  7. [Machine Learning] 梯度下降法的三种形式BGD、SGD以及MBGD

    在应用机器学习算法时,我们通常采用梯度下降法来对采用的算法进行训练.其实,常用的梯度下降法还具体包含有三种不同的形式,它们也各自有着不同的优缺点. 下面我们以线性回归算法来对三种梯度下降法进行比较. ...

  8. MySQLdb的一些经验

    遇到过的几类问题: 如果保持长连接,即使在mysql数据库默认的connection timeout内,也有可能出现"mysql server has gone away".还有另 ...

  9. Linux学习之十--.Net Core环境搭建以及Nginx的搭建

    一.Centos7下.Net Core 环境安装: 链接:https://www.microsoft.com/net/core#linuxcentos 按照步骤来: yum install libun ...

  10. jquery.nicescroll.js可全屏可改滚动条颜色的滚动条插件-推荐

    有一款很棒的插件 http://www.ijquery.cn/?p=666