web-sso-client

2021-06-22 03:04

阅读:594

标签:catch   art   tostring   cli   cookies   pcl   通过   过程   initial   

3.2.2具有SSO功能的web应用源代码解析
要实现WEB-SSO的功能,只有身份认证服务是不够的。这点很显然,要想使多个应用具有单点登录的功能,还需要每个应用本身的配合:将自己的身份认证的服务交给一个统一的身份认证服务-SSOAuth。SSOAuth服务中提供的各个方法就是供每个加入SSO的Web应用来调用的。
一般来说,Web应用需要SSO的功能,应该通过以下的交互过程来调用身份认证服务的提供的认证服务:
  • Web应用中每一个需要安全保护的URL在访问以前,都需要进行安全检查,如果发现没有登录(没有发现认证之后所带的cookie),就重新定向到SSOAuth中的login.jsp进行登录。
  • 登录成功后,系统会自动给你的浏览器设置cookie,证明你已经登录过了。
  • 当你再访问这个应用的需要保护的URL的时候,系统还是要进行安全检查的,但是这次系统能够发现相应的cookie。
  • 有了这个cookie,还不能证明你就一定有权限访问。因为有可能你已经logout,或者cookie已经过期了,或者身份认证服务重起过,这些情况下,你的cookie都可能无效。应用系统拿到这个cookie,还需要调用身份认证的服务,来判断cookie时候真的有效,以及当前的cookie对应的用户是谁。
  • 如果cookie效验成功,就允许用户访问当前请求的资源。
以上这些功能,可以用很多方法来实现:
  • 在每个被访问的资源中(JSP或Servlet)中都加入身份认证的服务,来获得cookie,并且判断当前用户是否登录过。不过这个笨方法没有人会用:-)。
  • 可以通过一个controller,将所有的功能都写到一个servlet中,然后在URL映射的时候,映射到所有需要保护的URL集合中(例如*.jsp,/security/*等)。这个方法可以使用,不过,它的缺点是不能重用。在每个应用中都要部署一个相同的servlet。
  • 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");
    } 
.....
.....
 
}
以上的初始化的源代码有两点需要说明:一是有两个需要配置的参数SSOServiceURL和SSOLoginPage。因为当前的Web应用很可能和身份认证服务(SSOAuth)不在同一台机器上,所以需要让这个filter知道身份认证服务部署的URL,这样才能去调用它的服务。另外一点就是由于身份认证的服务调用是要通过http协议来调用的(在本样例中是这样设计的,读者完全可以设计自己的身份服务,使用别的调用协议,如RMI或SOAP等等),所有笔者引用了apache的commons工具包(详细信息情访问apache 的网站http://jakarta.apache.org/commons/index.html),其中的“httpclient”可以大大简化http调用的编程。
下面看看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
                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请求。
SSOFilter
*.jsp
 
下面还有几个主要的函数需要说明:
    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)替我自动生成的。

web-sso-client

标签:catch   art   tostring   cli   cookies   pcl   通过   过程   initial   

原文地址:http://www.cnblogs.com/lexiaofei/p/7172232.html


评论


亲,登录后才可以留言!