zoukankan      html  css  js  c++  java
  • 简单实现web单点登录

    主要参考文档:http://blog.csdn.net/jimmy609/article/details/18605781

    1、工程总体结构:

    2、修改C:WindowsSystem32driversetchosts文件,加入以下一段配置:

    127.0.0.1    wangyu.prc.sun.com

    这样可以保证3个web应用处于同一个域中(和cookie访问有关),并且不用修改作者提供的示例代码。

    3、首先看SSOWebDemo1这个应用第一次访问时,

        <filter>
            <filter-name>SSOFilter</filter-name>
            <filter-class>sso.SSOFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>SSOFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

    其中SSOFilter的doFilter方法如下:

        /**
         *
         * @param request The servlet request we are processing
         * @param result The servlet response we are creating
         * @param chain The filter chain we are processing
         *
         * @exception IOException if an input/output error occurs
         * @exception ServletException if a servlet error occurs
         */
        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 ="";
            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信息,则判断该cookie是否有效(即已经成功通过SSO单点认证服务器)
                        result = SSOService(cookieValue);
                        if (debug) log("found cookies!");
                    }
                }
            }
            if (result.equals("failed")) {
                //如果没有携带cookie信息或者cookie验证失效,则需要重新登录SSO验证服务器
                response.sendRedirect(SSOLoginPage+"?goto="+url);
            } else if (qstring.indexOf("logout") > 1) {
                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);
                }
            }   
        }

    其中SSOLoginPage 为"http://wangyu.prc.sun.com:8080/SSOAuth/login.jsp",在首次访问这个web应用时会请求这个URI进行SSO登陆验证,否则会调用SSOService方法验证该客户端是否已经通过验证(通过携带的cookie),SSOService方法如下:

        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();
            }
        }

    其中SSOServiceURL为"http://wangyu.prc.sun.com:8080/SSOAuth/SSOAuth",所以这个方法会请求URI:

    http://wangyu.prc.sun.com:8080/SSOAuth/SSOAuth?action=authcookie&cookiename=xxx验证该客户端是否有效。

    如果客户端携带的cookie有效则通过该Filter,继续处理该请求。

    4、这里的SSO验证使用的是一个Servlet,主要的功能是验证初始的用户名密码是否合法、产生cookie发送到客户端、以及验证客户端的cookie是否有效。

    4.1、定义的成员变量

        //保存用户信息(对应的用户名和密码)
        static private ConcurrentMap<String, String> accounts;
        //保存已经登录的用户信息(对应的cookie信息和用户名)
        static private ConcurrentMap<String, String> SSOIDs;
    ConcurrentMap为线程安全的集合类。

    4.2、假设以下的四个用户为合法用户

        public void init(ServletConfig config) throws ServletException {
            super.init(config);
            SSOIDs = new ConcurrentHashMap<String, String>();
            accounts = new ConcurrentHashMap<String, String>();
            accounts.put("admin", "admin");
            accounts.put("wangyu", "wangyu");
            accounts.put("paul", "paul");
            accounts.put("carol", "carol");
        }

    4.3、处理该客户端第一次登陆的代码

        private void handlerFromLogin(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String pass = (String) accounts.get(username);
            if ((pass == null) || (!pass.equals(password)))
                getServletContext().getRequestDispatcher("/failed.html").forward(
                        request, response);
            else {
                String gotoURL = request.getParameter("goto");
                String newID = createUID();
                SSOIDs.put(newID, username);
                //登录的用户名和密码合法,往客户端写入一个cookie,值为自定义生成的id(一段字符串加上当前时间)
                Cookie wangyu = new Cookie(cookiename, "22222");
                wangyu.setDomain(".sun.com");
                // 60分钟之内cookie有效
                wangyu.setMaxAge(60 * 60);
                wangyu.setValue(newID);
                wangyu.setPath("/");
                response.addCookie(wangyu);
    
                System.out.println("login success, goto back url:" + gotoURL);
                if (gotoURL != null) {
                    PrintWriter out = response.getWriter();
                    response.sendRedirect(gotoURL);
                    out.close();
                }
            }
        }

    4.4、根据客户端传递过来的cookie的值,来判断该cookie是否合法(已登录并有效)

        /*
         * authentication from cookie, If exists and hold in MAP, return the user
         * name as content else return "failed"
         */
        /*
         * protected String authCookie(HttpServletRequest request){ Cookie[]
         * diskCookies = request.getCookies(); if (diskCookies == null) return
         * "failed"; for (Cookie cookie : diskCookies){
         * if(cookie.getName().equals(cookiename)){ String sessionContent = (String)
         * SSOIDs.get(cookie.getValue()); if (sessionContent == null) return
         * "failed"; else return sessionContent; }
         * 
         * } return "failed"; }
         */
    
        // static method used by other servlet in the same container
        static public String authCookie(String value) {
            String result = (String) SSOIDs.get(value);
            if (result == null)
                result = "failed";
            return result;
        }

    5、SSOWebDemo2的处理逻辑同SSOWebDemo1,也是一个SSOFilter控制单点登陆以及cookie的验证。因为SSOWebDemo1和SSOWebDemo2处在一个cookie的域中,所以SSO验证服务器为SSOWebDemo1产生的cookie,在SSOWebDemo2访问验证服务器时也会携带。

    6、运行效果

    6.1、环境tomcat6

    6.2、访问SSOWebDemo1并登陆

    6.3、访问SSOWebDemo2,这次不需要登陆

    7、整理代码zip

     http://download.csdn.net/detail/hx888/6888221

  • 相关阅读:
    AutoCAD.NET 二次开发(一) 自定义菜单及自动加载
    WSS 3.0部署备忘 一
    WSS 3.0部署备忘 四
    WSS 3.0部署备忘 三
    WSS 3.0部署备忘 二
    loj_1042
    loj_1045
    vim的学习笔记(3)
    Linux的磁盘与文件管理系统(1)
    文件与文件系统的压缩与打包
  • 原文地址:https://www.cnblogs.com/wenwujuncheng/p/3535135.html
Copyright © 2011-2022 走看看