单点登陆系统,像CAS这样的东西大都比较复杂,上首慢,上来就要配个SSL,然后才能走下去,但很多时候我要搞这个SSL干吗呢?我只是需要一个单点登陆系统。至于SSL加密不加密,那是另外一事情,不想一开始就把事情搞得那么复杂!
其实单点登陆的主要思想是:
如果在一个中央(Central)服务器上已经登陆,当我再次登陆一个结盟(Federal)站点的时候,应该能识别我在中央服务器的登陆信息,从而在结盟服务器通过身份验证。主要的活动就是这个。
当在一个服务器上登陆时,我可以产生会话对象,并保存在服务器端,但是我如何在另外一个网站读取它呢?简而言之,就在中央(Central)服务器和结盟(Federal)站点服分别设立如下程序
中央(Central)服务器:
SSOMain,包含如下3个基本功能:
1) SaveSessionToMap
2)ReadTicketFromCookie
3)VlidateTicket
结盟(Federal)站点:
SsoClient,包含如下2个基本功能:
1)请求主站的ReadTicketFromCookie,返回结盟(Federal)站点:
2)请求主站的VlidateTicket,给出当前登陆信息。
废话少说,下面贴出代码。
SSOServlet.java
package sso;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletConfig;
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 sso.SSOUserMap;
/**
* Handles logins for the Central Authentication Service.
*/
public class SSOServlet extends HttpServlet
{
public SSOUserMap ssoUserMap = null;
public static final String CookieName = "ssocookie";
public void init(ServletConfig config) throws ServletException
{
ssoUserMap = new SSOUserMap();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException, NullPointerException
{
doGet(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException, IllegalArgumentException,NullPointerException
{
String action = request.getParameter("action");
if ( action == null )
{
if ( request.getParameter("username") != null )
{
try
{
String userName = request.getParameter("username");
userName = URLEncoder.encode(userName,"GBK");
System.out.println("*******************userName=" + userName);
ssoUserMap.addUser(userName);
Cookie wangyu = new Cookie(CookieName, userName);
// wangyu.setDomain(domainname);
wangyu.setMaxAge( 24 * 60 * 60 );
// String s = "wangzheng";
wangyu.setValue(userName);
wangyu.setPath("/");
response.addCookie(wangyu);
response.sendRedirect("ReadCookie2.jsp");
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
response.sendRedirect("ReadCookie2.jsp");
}
}
} else if ( action.equals("readCookie") )
{
String cookieValue = "";
String ticket = "";
Cookie[] diskCookies = request.getCookies();
if ( diskCookies != null )
{
for (int i = 0; i < diskCookies.length; i++)
{
if ( diskCookies[i].getName().equals(CookieName) )
{
cookieValue = diskCookies[i].getValue();
// out.print(cookieValue);
}
}
}
System.out.println("*******************readCookie=" + cookieValue);
if ( cookieValue != null && !cookieValue.equals("") )
{
//cookieValue = URLDecoder.decode(cookieValue,"GBK");
ticket = ssoUserMap.getTicket(cookieValue);
if( ticket == null || ticket.equals("") ){
ssoUserMap.addUser(cookieValue);
ticket = ssoUserMap.getTicket(cookieValue);
}
}
String gotoURL = request.getParameter("goto");
if ( gotoURL != null && !gotoURL.equals("") )
response.sendRedirect(gotoURL + "?ticket=" + ticket);
} else if ( action.equals("validate") )
{
String ticket = request.getParameter("ticket");
String userName = "";
try
{
userName = ssoUserMap.getUser(ticket);
System.out.println("*******************ticket=" + ticket
+ ",userName=" + userName);
userName = URLDecoder.decode(userName,"GBK");
System.out.println("*******************ticket=" + ticket
+ ",userName2=" + userName);
response.setContentType("text/html; charset=gb2312");
PrintWriter out = response.getWriter();
if ( userName != null && !userName.equals("") )
out.println("yes\n" + userName + "\n");
else
out.println("no\n\n");
} catch (UnsupportedEncodingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if ( action.equals("viewMap") )
{
try
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
for (Iterator i = ssoUserMap.sso_user_map.entrySet().iterator(); i
.hasNext();)
{
Map.Entry e = (Map.Entry) i.next();
out.println("<br>*****" + e.getKey() + "=" + e.getValue());
}
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
java端的 sso.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.net.*,java.io.*"%>
<%
//这个程序一般是运行在结盟的服务器上。request.getContextPath()要换成主站的网址.
String ticket = request.getParameter("ticket");
if (ticket == null ) {
//没有ticket,直接调用主站程序去调用读Cookie的程序,读出ticket,再拿过来验证。
String url = "http://www.centralserver.com:8080/sso/ssoservlet?action=readCookie&goto=goto.jsp";
response.sendRedirect(url);
return;
} else {
//out.println("====" + ticket);
//如果有Ticket,那么直接验证,返回用户名。
String url = "http://www.centralserver.com:8080/sso/ssoservlet?action=validate&ticket=" + ticket;
URL weblogic = new URL(url);
BufferedReader in = new BufferedReader(
new InputStreamReader(
weblogic.openStream()));
String ret = in.readLine();
out.println(ret);
}
%>
PHP client段的代码主要用curl来实现调用central段的VlidateTicket, sso.php
<?php $url = 'http://10.144.176.110:6080/share/page/dologin?username=xxxx&password=111111&success=/share&failure=/share/page/type/login'; $post = 1; $returntransfer = 1; $port = 80; $header = 0; $nobody = 0; $followlocation = 1; $request = ''; $ch = curl_init(); $options = array(CURLOPT_URL => $url, CURLOPT_HEADER => $header, CURLOPT_NOBODY => $nobody, CURLOPT_PORT => $port, CURLOPT_POST => $post, CURLOPT_POSTFIELDS => $request, CURLOPT_RETURNTRANSFER => $returntransfer, CURLOPT_FOLLOWLOCATION => $followlocation, //CURLOPT_COOKIEJAR => $cookie_jar, //CURLOPT_COOKIEFILE => $cookie_jar, CURLOPT_ENCODING=>"UTF-8", CURLOPT_REFERER => $url ); curl_setopt_array($ch, $options); $temp = ""; echo "<br>temp=".$temp; $temp = curl_exec($ch); curl_errno($ch); curl_close($ch); echo "<br>temp=".$temp; ?>
本文参考了:
http://www.cnblogs.com/huc87/archive/2009/08/21/1551398.html
自己的源码:CuteSSO.rar