要做个单点登陆的例子,要有以下:
1
用户身份认证服务器
2
两个应用系统。用户身份认证系统是提供认证功能和登陆功能的,应用系统是模拟跨域访问。项目结构如下图所示:
其中有三个项目:
Client
、
Client2
、
Server
。
Client
和
Client2
是应用系统用于模拟跨域访问的;而
Server
系统是用户身份验证的。三个都是
Web
工程。既然是
web
工程,那么众所周知
Web
协议(也就是
HTTP
)是一个无状态的协议。服务器是如何记录和保持登陆信息呢?
浏览器访问一次服务器,就和服务器建立一次
Sockect
连接当服务器响应完毕时,就会断口连接。第二次访问的时候模式一样。为了保存信息软件师们发明了两个东西:
Session
和
Cookie
。
Session
是保持在服务端的会话信息,
Cookie
是持久化在客户端的会话信息。浏览器每次访问
Web
站点时都把此站点相应的
Cookie
信息发送给服务器,服务器从
Cookie
中取相应的字段(
sessionId
),然后根据字段在服务器的缓存中查找相应的
Session
,如果没查到则
Request
对象会自动新建一个
Session
对象。这些是基础没有这些知识很难理解如何实现
SSO
的。
首先建好上面三个工程,然后各自建相应的过滤器和页面(源码
)可以先下载下来导入
Eclipse
中,启动
Tomcat
服务器。
第一:
client
端的
AuthFilter
代码
package org.hundsun.sso.filter.auth;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
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;
//登陆验证
public class AuthFilter implements Filter {
private String casUrl;
private String CASSERVER_URL;
private String SERVER_NAME;
private String VARERVER_URL;
private ConnectionUtil connectionUtil;
public void init(FilterConfig config) throws ServletException {
CASSERVER_URL=config.getInitParameter("casServer");
SERVER_NAME=config.getInitParameter("serverName");
VARERVER_URL=config.getInitParameter("varServer");
connectionUtil = new ConnectionUtil();
casUrl = new StringBuffer().append(CASSERVER_URL).append("?serverName=").append(SERVER_NAME).toString();
System.out.println(casUrl);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
HttpServletResponse response_ = (HttpServletResponse) response;
HttpServletRequest request_ = (HttpServletRequest) request;
//获得Ticket
String ticket = request.getParameter("ticket");
//转跳状态
boolean doFilter = false;
String CAS_USRR=(String)request_.getSession().getAttribute("CAS_USRR");
//如果已经登陆
if ( CAS_USRR!= null&&!"".equals(CAS_USRR)){
System.out.println("用户已经登录,转发用户请求");
System.out.println("CAS_USRR:"+CAS_USRR);
doFilter = true;
}
else
{
System.out.println("用户没有登录,验证用户ticket");
System.out.println("ticket详细如:"+ticket);
//Ticket不为空
String userName = null;
//解析用户信息
if (ticket != null && (userName = connectionUtil.getUserName(ticket)) != null) {
System.out.println("验证用户ticket成功!");
request_.getSession().setAttribute("CAS_USRR", userName);
doFilter = true;
}else{
System.out.println("验证用户ticket失败或ticket为空!");
}
}
if(doFilter)
chain.doFilter(request, response);
else {
//转跳到CAS服务器
System.out.println("用户没有登录且没携带ticket,转跳到CAS服务器登录验证!");
System.out.println("ticket验证地址:"+casUrl);
response_.sendRedirect(casUrl);
}
}
public void destroy() {
}
private class ConnectionUtil {
public String getUserName(String ticket) {
HttpURLConnection connection = null;
BufferedReader bfReader = null;
String userName = null;
try
{
//连接CAS验证服务器
System.out.println("连接CAS验证服务器!ticket:"+ticket);
String url=VARERVER_URL + "?ticket=" + ticket;
System.out.println("验证服务器URL:"+url);
connection = (HttpURLConnection) new URL(url).openConnection();
connection.connect();
bfReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
//获得解密后的用户名
userName = bfReader.readLine();
System.out.println("CAS验证服务器还回结果(userName):"+userName);
}
catch(Exception e)
{
throw new RuntimeException(e);
}
finally
{
try
{
if(bfReader!=null)bfReader.close();
if(connection!=null)connection.connect();
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
return userName;
}
}
}
这个是
client
端的验证用户是否登陆已经是否含有
tickect
信息的过滤器。
在上面的代码需要用到的参数在
web.xml
配置了,具体如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<filter>
<filter-name>autoFilter</filter-name>
<filter-class>org.hundsun.sso.filter.auth.AuthFilter</filter-class>
<init-param>
<param-name>casServer</param-name>
<param-value>http://127.0.0.1:8888/Server/login</param-value>
<description>认证服务器地址</description>
</init-param>
<init-param>
<param-name>varServer</param-name>
<param-value>http://127.0.0.1:8888/Server/server</param-value>
<description>服务器地址</description>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://127.0.0.1:8888/Client/welcome.jsp</param-value>
<description>跳转页面</description>
</init-param>
</filter>
<filter-mapping>
<filter-name>autoFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
其次也就是用户验证服务,有
LoginServer
和
ValidationServer
两个
Servlet
,
LoginServer
是检验用户
cookies
中是否含有
tickect
,然后重定向到验证服务中,而
ValidationServer
就是验证服务。
认证服务的配置信息在
web.xml
中:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>org.hundsun.sso.listener.KeyListener</listener-class>
</listener>
<servlet>
<servlet-name>LoginServer</servlet-name>
<servlet-class>org.hundsun.sso.service.LoginServer</servlet-class>
</servlet>
<servlet>
<servlet-name>ValidationServer</servlet-name>
<servlet-class>org.hundsun.sso.service.ValidationServer</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServer</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ValidationServer</servlet-name>
<url-pattern>/server</url-pattern>
</servlet-mapping>
</web-app>
LoginServer
代码:
public class LoginServer extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 发出请求的Client
String serverName = request.getParameter("serverName");
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies)
{
if (cookie.getName().equals("CAS")) {
// 生成Ticket
String ticket = "CAS" + ":" + cookie.getValue();
String url = new StringBuffer().append(serverName).append("?ticket=").append(ticket).toString();
response.sendRedirect(url);
return;
}
}
}
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
return;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
ValidationServer
代码:
import org.hundsun.sso.utiil.RSAUtil;
//验证服务
public class ValidationServer extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String ticket = request.getParameter("ticket");
String serverName = request.getParameter("serverName");
String name = request.getParameter("name");
String pass = request.getParameter("pass");
//优先验证ticket信息
if(ticket!=null)
{
try {
System.out.println("收的的ticket为:"+ticket);
String[] result = ticket.split(":");
//验证服务器信息和密码
System.out.println("验证密码:"+result[0]);
System.out.println("验证信息:"+result[1]);
response.getWriter().print(result[1]);
return;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//验证表单登录信息
else
{
System.out.println("name:"+name);
System.out.println("pass"+pass);
//登陆成功后将信息保存到Cookie
Cookie cookie = new Cookie("CAS", name);
cookie.setMaxAge(-1);
response.addCookie(cookie);
String url = new StringBuffer().append(serverName).append("?ticket=").append("CAS" + ":" + name).toString();
response.sendRedirect(url);
return;
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
以上是代码,具体的流程序列图如:
运行下可以实现了传说中的
SSO
了。
- 大小: 201.3 KB
- 大小: 29.2 KB
分享到:
相关推荐
尚缺少一些功能,将在以后的文章中介绍,其中包括流,分页,基准测试以及具有更短生命周期令牌,JWT令牌,单点登录(可能使用Auth0之类的服务),IP的更高级的安全模型。基于的速率限制(使用Cloudfla
尚缺少一些功能,将在以后的文章中介绍,其中包括流传输,分页,基准测试以及具有更短生命周期令牌,JWT令牌,单点登录(可能使用Auth0之类的服务),IP的更高级的安全模型。基于的速率限制(使用Cloudflare工作者)...
4篇文章,介绍如何利用IBMTivoliAccessManager来提供租户感知功能、保护应用程序资源以及提供单点登录功能。当前,云平台和基于云的解决方案已经成为现实。越来越多的企业在利用宿主软件、解决方案和服务的优势,将...
网管教程 从入门到精通软件篇 ★一。★详细的xp修复控制台命令和用法!!! 放入xp(2000)的光盘,安装时候选R,修复! Windows XP(包括 Windows 2000)的控制台命令是在系统出现一些意外情况下的一种非常有效的...
《大话Oracle RAC:集群 高可用性 备份与恢复》按照“发现问题→解决问题→实践与理论相结合”的方式进行介绍,首先对现实问题进行分析,然后提供合适的解决方案,最后自然地引出Oracle中的理论知识点,这种讲解...
《大话Oracle RAC集群、高可用性、备份与恢复》按照“发现问题→解决问题→实践与理论相结合”的方式进行介绍,首先对现实问题进行分析,然后提供合适的解决方案,最后自然地引出Oracle中的理论知识点,这种讲解方法...
•单方面强制征税 •税的合法性不足 •征管混乱随意 参考阅读:纳税“光荣”吗? 第四章 税制改良的未来 •怎样的税制才算优良 •历史与现实:如何走向宪政税制 参考阅读:深圳公民的“公共预算之旅” 下篇•税收...
这篇文章提出了一个基于我们的公式重建囊肿幻象的图像。讨论了图像重建中一些具有现实意义的问题。具体地说,引入了一种增强模型来解决ROI外回波的不完全阻塞问题。还介绍了一种列加权算法来最小化滤波器系数的数目...
人工智能作文600字 人工智能作文600字四篇 人工智能作文600字 篇1 随着时代的进步,科技在不断发展,人工智能以各种形式出现在我们的生活中,小到 一片几纳米的芯片,大到整个互联网的交互系统,可以说我们的生活离...
人工智能作文 【实用】人工智能作文锦集5篇 人工智能作文 篇1 随着时代的进步,科技在不断发展,人工智能以各种形式出现在我们的生活中,小到 一片几纳米的芯片,大到整个互联网的交互系统,可以说我们的生活离不开...
篇一:《机器人发展现状及未来趋势》 机 人未 展 趋 状 器 发 现 及 来 势 一、 机器人现状及国内外发展趋势 国外机器人领域发展近几年有如下几个趋势: 1.工业机器人性能不断提高(高速度、高精度、高可靠性、便于...
好在这些总算有点回报 , 在 HDC-NB 群叫嚷了一下成果 , 几个兄弟让我写个教程 , 我斗胆写篇文章让大家分享下我的经验 . 如何制造软路由器 , 首先我们需要虚拟机 , 咋一听 , 这玩意高深啊 , 肯定跟编程有关 , 俺门...
这一篇主要分享下数据分析的流程。 一、关键数据 每个B2C电子商务网站的定位和客户不同,运营的情况也千差万别,考察用户访问、 内容浏览和商业行为的关键数据,就能够判断网站运营的基本状况。 1.独立用户访问量:...
一、人工智能概述 人工智能到目前为止还没有一个统一的,明确的定义,其原因大致有以下两点:(一)人工智能不是一种单纯属于某一个学科的知识而是众多学科相互渗透,融合的复杂综合体,它涉及计算机科学、数学、语言...
—— 从总体概述到细节的讨论 —— 使高效的 Web 开发成为现实。他还揭开了 Ajax 核心概念的神秘 面纱,包括 XMLHttpRequest 对象。 五年前,如果不知道 XML,您就是一只无人重视的丑小鸭。十八个月前,Ruby 成了...
为了加强你对类的理解,我们再做一个类,做一个形状的类,形状的范围广了点, 我们就做个 矩形吧,先分析一下,想一想从两方面分析,矩形的属性都有什么?矩形的功能都有什么? class 矩形 LAMP 大讲堂PHP 面向对象...