[原创]CAS 3.2 中文帐户乱码问题完全解决方案

[原创]CAS 3.2 中文帐户乱码问题完全解决方案
2008-06-14 13:50

CAS 3.2虽然有中文界面,但是确是不支持中文账号和密码登录的。
CAS 3.2不支持中文帐户和密码登录体现在两个方面:
        1、中文帐户和密码不能在cas登录页面正常登录。
        2、中文帐户在用户登录后应用端服务请求cas服务器验证并返回用户登录帐户时,cas服务器的返回结果出现乱码。(下图中红色圈起的步骤)
下面就这两个方面分别给出解决方案。

 

1、中文帐户和密码不能在cas登录页面正常登录。

      为了解决这个问题,需要给CAS的配置文件加一个过滤器EncodingFilter(就像传统JSP网站解决中文问题的方法一样)

<filter>
        <description>EncodingFilter</description>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>org.leoframework.web.EncodingFilter</filter-class>
        <init-param>
            <description>encoding_charset</description>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <description>ignore?</description>
            <param-name>ignore</param-name>
            <param-value>true</param-value>
        </init-param>
</filter>
<filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>

      这个filter要在所有filter的最前面配置。

      其中org.leoframework.web.EncodingFilter为笔者自己开发的框架LeoFramework中的一个类,其实EncodingFilter类型的实现很简单,也可以自己实现。下面是这个类的代码:

/*
* EncodingFilter.java
*/

package org.leoframework.web;
import javax.servlet.*;
import java.io.IOException;
/**
*
* @author Leo
*/
public class EncodingFilter implements Filter {
   
    protected String encoding = null;
    protected FilterConfig filterConfig = null;
    protected boolean ignore = true;
   
    public void destroy() {
       
        this.encoding = null;
        this.filterConfig = null;
       
    }
   
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {
       
// Conditionally select and set the character encoding to be used
        if (ignore || (request.getCharacterEncoding() == null)) {
            String encoding = selectEncoding(request);
            if (encoding != null)
                request.setCharacterEncoding(encoding);
        }
       
// Pass control on to the next filter
        chain.doFilter(request, response);
       
    }
   
    public void init(FilterConfig filterConfig) throws ServletException {
       
        this.filterConfig = filterConfig;
        this.encoding = filterConfig.getInitParameter("encoding");
        String value = filterConfig.getInitParameter("ignore");
        if (value == null)
            this.ignore = true;
        else if (value.equalsIgnoreCase("true"))
            this.ignore = true;
        else if (value.equalsIgnoreCase("yes"))
            this.ignore = true;
        else
            this.ignore = false;
       
    }
   
    protected String selectEncoding(ServletRequest request) {
       
        return (this.encoding);
       
    }
   
}

       然后要在数据库连接中显示声明数据库所用的编码,笔者用的是Mysql数据库utf8编码,所以数据库连接的声明应该为:

       在cas.properties文件中的写法为:
db.url=jdbc:mysql://localhost:3306/passport_db?useUnicode=true&characterEncoding=utf-8
       在deployerConfigContext.xml可以通过${db.url}来调用这个配置,如:
<property name="url" value="${db.url}" />

       要是在xml文件中的<value></value>中间&要写成&amp; 如下为示例:
<property name="url">

<value>jdbc:mysql://localhost:3306/passport_db?useUnicode=true&amp;characterEncoding=utf-8</value>
</property>

2、中文帐户在用户登录后应用端服务请求cas服务器验证并返回用户登录帐户时,cas服务器的返回结果出现乱码。

       这个问题是由cas服务返回的页面没有设置对应的编码引起的。
       cas服务支持多种协议,他们有:cas1.0 cas2.0 Saml1.0 等。这些协议对应的返回验证结果页面是不同的,修改的方法也不一样。这里就cas1.0和cas2.0协议给出乱码的解决方案。(Saml1.0的解决方法和cas1.0近似)请根据你的系统所使用的协议来选择做相应的修改。

       cas1.0:
       cas1.0的验证结果页面是通过cas-server-3.2.1-release源码目录中的cas-server-3.2.1-release/cas-server-3.2.1/cas-server-core/src/main/java/org/jasig/cas/web/view目录下的Cas10ResponseView.java文件来定义的。
       乱码解决办法:在原代码中加入以下红色部门代码
       response.setContentType("text/xml;charset="+pagecharset);
        if (this.successResponse) {
           String userid=assertion.getChainedAuthentications().get(0).getPrincipal().getId();
           response.getWriter().print("yes/n" + userid + "/n");
        } else {
            response.getWriter().print("no/n/n");
        }
       其中pagecharset为页面编码,可以换为你想要的编码(gbk或是gb2312或是utf-8)
        修改完后,要重新编译cas-server-core,做法是,先安装Maven(Maven安装与配置),然后在DOS提示符下进入目录:{你的cas源码所在目录}/cas-server-3.2.1-release/cas-server-3.2.1/cas-server-core/
       运行命令:mvn package install
        如果你是第一次编译,这个过程会相当长,因为mvn要为cas的所有依赖库建议一个本地的repository(18m),建立repository的过程要通过网络下载很多文件。本地repository所在的位置:{用户目录}/.m2/,如在windows中这个目录就是C:/Documents and Settings/username/.m2
       如果你不想再次编译的话,留下你的邮箱,我可以把编译好的文件发给你。

      
cas2.0:
       cas2.0协议的验证结果页面是通过目录:cas/WEB-INF/view/jsp/protocol/2.0/ 下定义的jsp(jstlview)模板页面来定义的。
       casProxySuccessView.jsp:对应验证成功的页面(这个页面还包含用户登录的帐户名)。
       casServiceValidationFailure.jsp:对应验证失败页面。
       乱码解决办法:
       在casProxySuccessView.jsp和casServiceValidationFailure.jsp页面代码的最前面加上:<%@page pageEncoding="pagecharset"%>
       其中pagecharset为页面编码,可以换为你想要的编码(gbk或是gb2312或是utf-8)

附:

我修改后的Cas10ResponseView.java:

/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
*
http://www.ja-sig.org/products/cas/overview/license/
*/
package org.jasig.cas.web.view;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jasig.cas.validation.Assertion;

/**
* Custom View to Return the CAS 1.0 Protocol Response. Implemented as a view
* class rather than a JSP (like CAS 2.0 spec) because of the requirement of the
* line feeds to be "/n".
*
* @author Scott Battaglia
* @version $Revision: 42053 $ $Date: 2007-06-10 09:17:55 -0400 (Sun, 10 Jun 2007) $
* @since 3.0
*/
public final class Cas10ResponseView extends AbstractCasView {

    /**
     * Indicate whether this view will be generating the success response or
     * not.
     */
    private boolean successResponse;

    protected void renderMergedOutputModel(final Map model,
        final HttpServletRequest request, final HttpServletResponse response)
        throws Exception {
        final Assertion assertion = getAssertionFrom(model);
       
        String charset=request.getParameter("charset");
        if(charset==null||"".equals(charset)){
        charset="utf-8";
        }
       
        response.setContentType("text/xml;charset="+charset);
        if (this.successResponse) {
           String userid=assertion.getChainedAuthentications().get(0).getPrincipal().getId();
           response.getWriter().print("yes/n" + userid + "/n");
        } else {
            response.getWriter().print("no/n/n");
        }
    }

    public void setSuccessResponse(final boolean successResponse) {
        this.successResponse = successResponse;
    }
   
    public String chgCharset(String theStr, String theCharsetSrc, String theCharsetDet) {
        String rtnStr=theStr;
        if(theStr!=null&&theCharsetSrc!=null&&theCharsetDet!=null){
            try {
                rtnStr = new String(theStr.getBytes(theCharsetSrc),theCharsetDet) ;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            String thelog="chgCharset_Error:theCharsetSrc="+theCharsetSrc+"theCharsetDet"+theCharsetDet;
            System.out.println(thelog);
        }
        return rtnStr;
    }
}


我修改后的casProxySuccessView.jsp:

<%@page pageEncoding="UTF-8"%><%@ page session="false" %><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %><cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
   <cas:user>${fn:escapeXml(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.id)}</cas:user>
<c:if test="${not empty pgtIou}">
   <cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
</c:if>
<c:if test="${fn:length(assertion.chainedAuthentications) > 1}">
   <cas:proxies>
<c:forEach var="proxy" items="${assertion.chainedAuthentications}" varStatus="loopStatus" begin="0" end="${fn:length(assertion.chainedAuthentications)-2}" step="1">
    <cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy>
</c:forEach>
   </cas:proxies>
</c:if>
</cas:authenticationSuccess>
</cas:serviceResponse>

我修改后的casServiceValidationFailure.jsp:

<%@page pageEncoding="UTF-8"%><%@ page session="false" contentType="text/plain" %><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %><cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationFailure code='${code}'>
   ${fn:escapeXml(description)}
</cas:authenticationFailure>
</cas:serviceResponse>



cas1.0的验证结果格式:
       1、成功:"yes/n" + userid + "/n"
            yes
            userid


        2、失败:"no/n/n"
            no

  
caso2.0的验证结果格式:
       1、成功:
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
   <cas:user>userid</cas:user>


</cas:authenticationSuccess>
</cas:serviceResponse>


        2、失败:
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationFailure code='INVALID_TICKET'>
   未能够识别出目标 &#039;ST-4-NdWdS3eURcC7bdjovZyI-cas&#039;票根
</cas:authenticationFailure>
</cas:serviceResponse>

                

oracle数据库的driver url username password的写法:
     db.driver=oracle.jdbc.driver.OracleDriver
     db.url=jdbc:oracle:thin:@192.168.1.1:1521:xxxx
     db.username=xxxx
     db.password=xxxx


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值