本篇是对项目中用到单点登录的一些总结整理,具体的内容是结合自己找的一篇博客(下面会给大家贴出),主要是用cookie和ticket实现的。
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
WEB-SSO的实现
众所周知,Web协议(也就是HTTP)是一个无状态的协议。一个Web应用由很多个Web页面组成,每个页面都有唯一的URL来定义。用户在浏览器的地址栏输入页面的URL,浏览器就会向Web Server去发送请求。如下图,浏览器向Web服务器发送了两个请求,申请了两个页面。这两个页面的请求是分别使用了两个单独的HTTP连接。所谓无状态的协议也就是表现在这里,浏览器和Web服务器会在第一个请求完成以后关闭连接通道,在第二个请求的时候重新建立连接。
一般来说,Web应用需要SSO的功能,应该通过以下的交互过程来调用身份认证服务的提供的认证服务:
- Web应用中每一个需要安全保护的URL在访问以前,都需要进行安全检查,如果发现没有登录(没有发现认证之后所带的cookie),就重新定向到SSOAuth中的login.jsp进行登录。
- 登录成功后,系统会自动给你的浏览器设置cookie,证明你已经登录过了。
- 当你再访问这个应用的需要保护的URL的时候,系统还是要进行安全检查的,但是这次系统能够发现相应的cookie。
- 有了这个cookie,还不能证明你就一定有权限访问。因为有可能你已经logout,或者cookie已经过期了,或者身份认证服务重起过,这些情况下,你的cookie都可能无效。应用系统拿到这个cookie,还需要调用身份认证的服务,来判断cookie时候真的有效,以及当前的cookie对应的用户是谁。
- 如果cookie效验成功,就允许用户访问当前请求的资源
- 这里我们需要注意的是:你每次关闭一个浏览器,cookie就失效了,我们项目用的ticket也是,每次都是新建一个ticket的。
以上的功能我们是用filter实现的。
Filter是比较好的方法。符合Servlet2.3以上的J2EE容器就具有部署filter的功能。(Filter的使用可以参考JavaWolrd的文章http://www.javaworld.com/javaworld/jw-06-2001/jw-0622-filters.html)Filter是一个具有很好的模块化,可重用的编程API,用在SSO正合适不过。本样例就是使用一个filter来完成以上的功能。
package SSO;
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.*;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
public class SSOFilter implements Filter {
private FilterConfig filterConfig = null;
private String cookieName="WangYuDesktopSSOID";
private String SSOServiceURL= "http://wangyu.prc.sun.com:8080/SSOAuth/SSOAuth";
private String SSOLoginPage= "http://wangyu.prc.sun.com:8080/SSOAuth/login.jsp";
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
if (filterConfig != null) {
if (debug) {
log("SSOFilter:Initializing filter");
}
}
cookieName = filterConfig.getInitParameter("cookieName");
SSOServiceURL = filterConfig.getInitParameter("SSOServiceURL");
SSOLoginPage = filterConfig.getInitParameter("SSOLoginPage");
}
.....
.....
}
下面看看filter的主体方法doFilter():
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
if (debug) log("SSOFilter:doFilter()");
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String result="failed";
String url = request.getRequestURL().toString();
String qstring = request.getQueryString();
if (qstring == null) qstring ="";
//检查http请求的head是否有需要的cookie
String cookieValue ="";
javax.servlet.http.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();
//如果找到了相应的cookie则效验其有效性
result = SSOService(cookieValue);
if (debug) log("found cookies!");
}
}
}
if (result.equals("failed")) { //效验失败或没有找到cookie,则需要登录
response.sendRedirect(SSOLoginPage+"?goto="+url);
} else if (qstring.indexOf("logout") > 1) {//logout服务
if (debug) log("logout action!");
logoutService(cookieValue);
response.sendRedirect(SSOLoginPage+"?goto="+url);
} else {//效验成功
request.setAttribute("SSOUser",result);
Throwable problem = null;
try {
chain.doFilter(req, res);
} catch(Throwable t) {
problem = t;
t.printStackTrace();
}
if (problem != null) {
if (problem instanceof ServletException) throw (ServletException)problem;
if (problem instanceof IOException) throw (IOException)problem;
sendProcessingError(problem, res);
}
}
}
doFilter()方法的逻辑也是非常简单的,在接收到请求的时候,先去查找是否存在期望的cookie值,如果找到了,就会调用SSOService(cookieValue)去效验这个cookie的有效性。如果cookie效验不成功或者cookie根本不存在,就会直接转到登录界面让用户登录;如果cookie效验成功,就不会做任何阻拦,让此请求进行下去。在配置文件中,有下面的一个节点表示了此filter的URL映射关系:只拦截所有的jsp请求。
<filter-mapping>
<filter-name>SSOFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
下面还有几个主要的函数需要说明:
private String SSOService(String cookievalue) throws IOException {
String authAction = "?action=authcookie&cookiename=";
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod(SSOServiceURL+authAction+cookievalue);
try {
httpclient.executeMethod(httpget);
String result = httpget.getResponseBodyAsString();
return result;
} finally {
httpget.releaseConnection();
}
}
private void logoutService(String cookievalue) throws IOException {
String authAction = "?action=logout&cookiename=";
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod(SSOServiceURL+authAction+cookievalue);
try {
httpclient.executeMethod(httpget);
httpget.getResponseBodyAsString();
} finally {
httpget.releaseConnection();
}
}
这两个函数主要是利用apache中的httpclient访问SSOAuth提供的认证服务来完成效验cookie和logout的功能。
其他的函数都很简单,有很多都是我的IDE(NetBeans)替我自动生成的。
上面的内容主要都是截取这位博主的博客,对我项目中用到单点登陆的总结,每个人需要了解,用到的可能也不同,想具体了解的可以去他的博客里查看,希望该博主也能原谅我的参考,谢谢~~~
http://my.oschina.net/leamon/blog/266711