牛骨文教育服务平台(让学习变的简单)
博文笔记

JForum论坛单点登录的几种实现方式 (CAS和Cookie)

创建时间:2007-08-04 投稿人: 浏览次数:186

JForum论坛单点登录的几种实现方式 (CASCookie)

 

王保政

Email:baozhengw@netease.com

 

2007-8-4

 

一、CAS实现Jforum的单点登录

 

()CAS客户端应用的web.xml配置

CASjforum的安装过程本文就不介绍了,下面是jforum配置CAS服务器连接需要在web.xml中添加的配置:

   <filter>

        <filter-name>CASFilter</filter-name>

        <filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class>

        <init-param>

            <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name>

            <param-value>https://localhost:8443/cas/login</param-value>

        </init-param>

        <init-param>

            <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>

            <param-value>https://localhost:8443/cas/proxyValidate</param-value>

        </init-param>

        <init-param>

          <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>

          <param-value>localhost:8000</param-value>

        </init-param>

    </filter>

    <filter-mapping>

        <filter-name>CASFilter</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

 

一开始我调试jforum的单点登录的时候,首先在地址栏输入http://localhost:8000/cas/login?service=http://localhost:8000/jforum/user.jsp

(其中user.jsp是我自己添加JSP页面做测试用 ),在CAS页面输入用户名和口令确认后,页面自动跳转到http://localhost:8000/jforum/user.jsp?ticket= ticket=ST-5-Ih4fJNYyWlhFfywfeOwuVAFZn1vKOOVAgpD-20

Ticket是生成的票据,然后用这个ticket做参数访问:

https://localhost:8443/cas/serviceValidate?service= http://localhost:8000/jforum/user.jsp&ticket= ST-5-Ih4fJNYyWlhFfywfeOwuVAFZn1vKOOVAgpD-20

如果成功,返回的页面中出现登录成功的用户名,打开html源文件,内容为:

<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">

       <cas:authenticationSuccess>

              <cas:user>admin</cas:user>

       </cas:authenticationSuccess>

</cas:serviceResponse>

如果失败,页面显示ticket "ST-2-4ffpnvHKv1NH5So7uWvFdVNrbHsaPAfROXx-20" not recognizedhtml源文件内容:

<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">

       <cas:authenticationFailure code="INVALID_TICKET">

              ticket "ST-2-4ffpnvHKv1NH5So7uWvFdVNrbHsaPAfROXx-20" not recognized

       </cas:authenticationFailure>

</cas:serviceResponse>

(二)Jforum配置单点登录

JforumWEB-INF/config目录下有一个SystemGlobals.properties文件,配置SSO需要更改此文件的几个配置参数:

authentication.type = sso

#CasUserSSO类用于CAS单点登录,下面将讲述此类的代码

sso.implementation = com.iss.common.sso.CasUserSSO

#CasCookieSSO是基于Cookie的一个简单的单点登录,代码见下文

#sso.implementation = com.iss.common.sso.CasCookieSSO

#下面的redirect我也不太清楚具体有什么用

sso.redirect = https://localhost:8443/cas/

(三)当把jforumweb.xmlCAS filter注释掉以后,使用下面的JSP通过CAS单点登录票据验证的一个示例,其中URL应带service参数,如:

http://localhost:8000/cas/login?service=http://localhost:8000/jforum/testsso.jsp

登录CAS成功后,返回的页面url带有一个ticket参数,见下面的返回URL:

http://localhost:8000/jforum/testsso.jsp?ticket=ST-5-VbM7tdMPeLD1WlH2ZGnocVGTbAY73ff4y17-20

Tomcat控制台显示下面的输出说明票据认证通过:

<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">

        <cas:authenticationSuccess>

                <cas:user>admin</cas:user>

        </cas:authenticationSuccess>

</cas:serviceResponse>

下面是testsso.jsp:

 

<%@ page contentType="text/html;charset=GBK"%>

 

<%@ page import="java.util.*"%> 

<%@ page import="net.jforum.context.RequestContext"%> 

<%@ page import="net.jforum.entities.UserSession"%> 

<%@ page import="net.jforum.util.preferences.ConfigKeys"%> 

<%@ page import="net.jforum.util.preferences.SystemGlobals"%> 

<%@ page import="org.apache.log4j.Logger"%> 

<%@ page import="net.jforum.sso.*"%> 

 

<%@ page import="java.io.*"%> 

<%@ page import="edu.yale.its.tp.cas.client.*"%> 

<%

    String username = null;

      String errorCode = null;

      String errorMessage = null;

      String xmlResponse = null;

      String ticket = request.getParameter("ticket");

    System.out.println("获取的ticket:"+ticket);

       ServiceTicketValidator sv = new ServiceTicketValidator();

        if(ticket != null)

        {

            try

            {

         

                sv.setCasValidateUrl("https://localhost:8443/cas/serviceValidate");

             sv.setServiceTicket(ticket);

                sv.setService("http://localhost:8000/jforum/testsso.jsp");

             sv.validate();  

             xmlResponse = sv.getResponse();

               

              if (sv.isAuthenticationSuccesful())

                {

                 username = sv.getUser();

                     System.out.println("认证成功,获得的用户名为:");

                     System.out.println(username);

             }

                else

                {

                  errorCode = sv.getErrorCode();

                    errorMessage = sv.getErrorMessage();

                     System.out.println("认证失败!!!!!!!!!!!");

             }

            }

            catch (Exception exc)

            {

               System.out.println(exc.getMessage());

          }

      }

%>

 

edu.yale.its.tp.cas.client.ServiceTicketValidatorcasclient.jar中的类。

 

()Jforumweb.xml中不配置CAS Filter时,如何实现单点登录类?

这种情况类似于(),但问题是如何在Java类中实现单点登录,而不是在jsp中实现。

我从网上找到一个名为CasUserSSO.java的程序,并按步骤(二)的说明将此类作为单点登录类配置,但编译运行后,在浏览器地址栏输入http://localhost:8000/cas/login?service=http://localhost:8000/jforum/user.jsp

(user.jsp是我自己写的一个显示简单输出的jsp文件, http://localhost:8000/jforum/user.jsp是我在CasUserSSO.java里面作为service参数的),CAS登录成功后Tomcat控制台没有显示单点登录的认证信息,好象CasUserSSO没有调用到,于是我修改了CasUserSSO.java,

sv.setService("http://localhost:8000/jforum/user.jsp")改为sv.setService(java.net.URLEncoder.encode(http://localhost:8000/jforum/forums/jforum.page?module=forums&action=list"));

重新编译运行后,地址栏中输入http://localhost:8000/cas/login?service= http%3A%2F%2Flocalhost%3A8000%2Fjforum%2Fforums%2Fjforum.page%3Fmodule%3Dforums%26action%3Dlist

注意service等号右面的必须是java.net.URLEncoder.encode转换后的字符串(http://localhost:8000/jforum/forums/jforum.page?module=forums&action=list转换后的字符串为http%3A%2F%2Flocalhost%3A8000%2Fjforum%2Fforums%2Fjforum.page%3Fmodule%3Dforums%26action%3Dlist)

 

注意地址栏中service后不要带空格,在地址栏输入http://localhost:8000/cas/login?service=http%3A%2F%2Flocalhost%3A8000%2Fjforum%2Fforums%2Fjforum.page%3Fmodule%3Dforums%26action%3DlistCAS登录后(我的jforum配的超级管理员帐号是admin/123),出现jforum页面,这说明CAS单点登录成功!!!

Tomcat控制台显示:

 

<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">

        <cas:authenticationSuccess>

                <cas:user>admin</cas:user>

        </cas:authenticationSuccess>

</cas:serviceResponse>

 

请大家一定要注意,在地址栏中service=后面的URL必须是encode转换后的,因为开始没转换,我还以为是CasUserSSO写的有问题,网上下载的CasUserSSO中的

sv.setCasValidateUrl("https://localhost:8443/cas/login");我认为是有问题的,会出现一个很奇怪的异常,显示信息为org.xml.sax.SAXParseException: The reference to entity "ticket" must end with the ";" delimiter.我改为:

sv.setCasValidateUrl("https://localhost:8443/cas/serviceValidate")则不会出现这个问题。见下面的CasUserSSO.java:

 

package com.iss.common.sso;

 

import net.jforum.context.RequestContext;

import net.jforum.entities.UserSession;

import net.jforum.util.preferences.ConfigKeys;

import net.jforum.util.preferences.SystemGlobals;

import org.apache.log4j.Logger;

import net.jforum.sso.*;

import java.util.*;

import java.net.*;

 

import edu.yale.its.tp.cas.client.*;

 

public class CasUserSSO implements SSO

{

    static final Logger logger = Logger.getLogger(CasUserSSO.class.getName());

    public String authenticateUser(RequestContext request)

    {

        String username = null;

      String errorCode = null;

      String errorMessage = null;

      String xmlResponse = null;

     // 开始setServiceTicket单点登录代码

 

      String ticket = request.getParameter("ticket");

        logger.info("获取的ticket:"+ticket);

 

       ServiceTicketValidator sv = new ServiceTicketValidator();

       

      if(ticket != null)

        {

                       try

            {

                logger.info("ticket为非空!!!!!!!!!!!!!!!!!");

                sv.setCasValidateUrl("https://localhost:8443/cas/serviceValidate");

                //sv.setCasValidateUrl("https://localhost:8443/cas/login");

                System.out.println(java.net.URLEncoder.encode("http://localhost:8000/jforum/forums/jforum.page?module=forums&action=list"));

                sv.setService(java.net.URLEncoder.encode("http://localhost:8000/jforum/forums/jforum.page?module=forums&action=list"));

                sv.setServiceTicket(ticket);

             logger.info("开始验证............");

             sv.validate();  

             xmlResponse = sv.getResponse();

                //System.out.println(xmlResponse);

              if (sv.isAuthenticationSuccesful())

                {

                 username = sv.getUser();

                    logger.info("认证成功,获得的用户名为:");

                    logger.info(username);

             }

                else

                {

                  errorCode = sv.getErrorCode();

                    errorMessage = sv.getErrorMessage();

                    logger.info("认证失败!!!!!!!!!!!");

             }

            }

            catch (Exception exc)

            {

               System.out.println(exc.getMessage());

          }

      }

        // 结束setServiceTicket单点登录代码

       

       /* System.out.println("开始获取用户名。。。");

        username = (String)request.getSessionContext().getAttribute("edu.yale.its.tp.cas.client.filter.user");

        System.out.println(username);

        System.out.println("结束获取用户名。。。");

 

        logger.info("登录用户为:"+username);*/

        return username;

    }

 

    public boolean isSessionValid(UserSession userSession,RequestContext request)

    {

        ServiceTicketValidator sv = new ServiceTicketValidator();

      String remoteUser =sv.getUser();  

        logger.info("RemoteUser");

        logger.info(remoteUser);

        //user has since logged out

      if (remoteUser == null && userSession.getUserId() != SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID))

        {

          return false;

      }

     

        // user has since logged in

      else if (remoteUser != null && userSession.getUserId() == SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID))

        {

          return false;

      <

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。