最近使用JeeCMS的系统需要用到CA认证,之前很是苦逼了一段时间毕竟是第一次接触类似的东西,没有专业的工程师指导,只给了一个demo和几个文档,当时真的是无从下手。幸好通过两个熬夜,不断的尝试终于成功了,下面就把具体内容分享一下。

关于CA认证是什么东西,我想大多数人都知道的,网上银行使用的key宝或者U盾都属于此列,使用数字证书和密钥加固重要密码的认证流程。也就是说,我手里有个钥匙盘,插入钥匙盘,输入钥匙盘的密码,才能通过该认证,否则拒绝通行。具体原理大家可以去百度百科上去熟悉(http://baike.baidu.com/view/356572.htm),此处不再赘言。

CA认证首先要有认证服务器,服务器可以配置认证关键字(相当于应用ID),产生认证原文,进行密码验证,返回认证结果和证书信息。本文主要说明的是客户端的配置和服务器端的交互过程。

涉及到的文件:前台登陆界面,后台两个servlet。

所采用认证方式登陆,则进行以下流程:

前台代码如下:

<!--CA认证开始-->
<script language="JavaScript" type="text/JavaScript">var xmlHttp = null;//启动函数$(document).ready(function(){//doDataProcess();//1.删除cookieforeach();//alert("ready");//2.判断登录类型;if(!window.ActiveXObject){alert("请使用IE浏览器(IE6-IE8)!");document.getElementById("face").disabled="disabled";setInputReadOnly(true);}checkLoginType();})  //下一个跳转方法checkLoginType//检测登陆方式function checkLoginType(){//alert("checkLoginType");var loginType  = 2;var isCaOrUser = true;if(loginType!=null){if(loginType=="1")//普通帐户密码登陆方法{divcontrol(0);}else if(loginType=="2")//ca登陆认证方式{divcontrol(1);}else if(loginType=="3")//两种登陆方式兼容{if(isCaOrUser=="true"){divcontrol(1);}else{divcontrol(0);}}else//默认为普通帐户密码登陆方法{divcontrol(0);}}else //默认为普通帐户密码登陆方法{divcontrol(0);}} //下一个跳转方法divcontrol//判断是否为ca登陆function divcontrol(isca){//alert("divcontrol");var flag ="";if(true==isca){//如果参数不为0flag =document.getElementById("face").value ;//取到当前的登陆方式,普通登陆还是认证登陆//alert(flag);}else{flag=isca}document.getElementById("realname").value = "";document.getElementById("username").value = "";document.getElementById("password").value = "";if(flag==1){//如果登陆方式是认证登陆doDataProcess();//3.服务器后台验证。setInputReadOnly(true);}else{   setInputReadOnly(false);}}//下一个跳转方法doDataProcessfunction setInputReadOnly(flag){if(flag){document.getElementById("realname").readOnly = true;document.getElementById("username").readOnly = true;document.getElementById("password").readOnly = true;  }   else{document.getElementById("realname").readOnly = false;document.getElementById("username").readOnly = false;document.getElementById("password").readOnly = false;}}function doDataProcess(){    //alert("doDataProcess");getAuth_Content();rightCheck();//testCheck(); }//下一个跳转方法rightCheck//获得认证原文getAuth_Content = function(){createXMLHttpRequest();//提交urlurl="random";xmlHttp.open("post",url,false);xmlHttp.onreadystatechange=ajaxBack;xmlHttp.send();  }//回调函数function   ajaxBack(){if(xmlHttp.readyState==4){if(xmlHttp.status == 200){//var resTxt =xmlHttp.responseText;$("#original").val(resTxt);}else{Ext.MessageBox.show({title : '提示',msg : '无法获取认证原文!',width :250,buttons:{"ok":"确定"},icon : Ext.MessageBox.WARNING });}}}//主要操作方法function rightCheck(){//获取认证原文//如果插入UKEY之后验证失败,直接跳出。var loginResult = 'null';   if("failure"==loginResult){Ext.MessageBox.show({title : '登录提示',msg : '用户不存在,请重试!',buttons:{"ok":"确定"},icon : Ext.MessageBox.WARNING});return ;}var Auth_Content =  $("#original").val();//此处为动态代码//alert("Auth_Content="+Auth_Content);document.getElementById("original_jsp").value = Auth_Content;var DSign_Subject = document.getElementById("RootCADN").value;if(Auth_Content==""){Ext.MessageBox.show({title : '提示',msg : '认证原文不能为空!',width :250,buttons:{"ok":"确定"},icon : Ext.MessageBox.WARNING });return;}else{//控制证书为一个时,不弹出证书选择框JITDSignOcx.SetCertChooseType(1);JITDSignOcx.SetCert("SC","","","",DSign_Subject,"");if(JITDSignOcx.GetErrorCode()!=0){//alert("错误码:"+JITDSignOcx.GetErrorCode()+" 错误信息:"+JITDSignOcx.GetErrorMessage(JITDSignOcx.GetErrorCode()));Ext.MessageBox.show({title : '提示',msg : '错误码:'+JITDSignOcx.GetErrorCode()+' 错误信息:'+JITDSignOcx.GetErrorMessage(JITDSignOcx.GetErrorCode()),width :250,buttons:{"ok":"确定"},icon : Ext.MessageBox.WARNING });return false;}else {var temp_DSign_Result = JITDSignOcx.DetachSignStr("",Auth_Content);if(JITDSignOcx.GetErrorCode()!=0){//alert("错误码:"+JITDSignOcx.GetErrorCode()+" 错误信息:"+JITDSignOcx.GetErrorMessage(JITDSignOcx.GetErrorCode()));Ext.MessageBox.show({title : '提示',msg : '错误码:'+JITDSignOcx.GetErrorCode()+' 错误信息:'+JITDSignOcx.GetErrorMessage(JITDSignOcx.GetErrorCode()),width :250,buttons:{"ok":"确定"},icon : Ext.MessageBox.WARNING });return false;}//如果Get请求,需要放开下面注释部分while(temp_DSign_Result.indexOf('+')!=-1) {temp_DSign_Result=temp_DSign_Result.replace("+","%2B");}document.getElementById("signed_data").value = temp_DSign_Result;}}var url = 'auth?original_jsp='+Auth_Content+'&signed_data='+temp_DSign_Result;readyFun(url);}//下一个跳转方法readyFun//创建xmlHttpfunction createXMLHttpRequest(){if(window.ActiveXObject){xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");}else if(window.XMLHttpRequest){xmlHttp = new XMLHttpRequest();}}var perainfo =  "";//通过ajax获取人员信息function readyFun(url){createXMLHttpRequest();//提交urlxmlHttp.open("get",url);xmlHttp.onreadystatechange=ajexBack;xmlHttp.send();//回调函数function   ajexBack(){if(xmlHttp.readyState==4){if(xmlHttp.status == 200){//由回调函数返回的信息切割成串var resultArr = xmlHttp.responseText.split(",");var validateResult = resultArr[0];//验证的结果var usercode = resultArr[1];//用户编码var realname = resultArr[2];//真实姓名if(validateResult != null &&validateResult !=""&&validateResult=="success"){}else{Ext.MessageBox.show({title : '提示',msg : '用户不存在,请重试',width :250,buttons:{"ok":"确定"},icon : Ext.MessageBox.WARNING });return ;}if(usercode != null && usercode != ""){document.getElementById("username").value = usercode;//设置用户编码document.getElementById("username").readOnly = true;//设置为只读}else{Ext.MessageBox.show({//失败的时候title : '提示',msg : '用户不存在,请重试',width :250,buttons:{"ok":"确定"},icon : Ext.MessageBox.WARNING });return ;}document.getElementById("realname").value = realname;document.getElementById("password").value = "password";document.getElementById("password").readOnly = true;document.getElementById("realname").readOnly = true;}else{Ext.MessageBox.show({title : '提示',msg : '连接服务器出错!',width :250,buttons:{"ok":"确定"},icon : Ext.MessageBox.WARNING });}}}}</script>
<!--CA认证结束-->

random对应RandomServlet,代码如下:

public class RandomServlet extends HttpServlet {private static final long serialVersionUID = 3923090461076418525L;private String tempURL = null,propertiesURL = null;private Properties props = null;/** 认证地址 */private final String KEY_AUTHURL = "authURL";/** 应用标识 */private final String KEY_APP_ID = "appId";/*** @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)*/public void init(ServletConfig cfg) throws ServletException {// 初始化程序跳转页面tempURL = cfg.getInitParameter("url");propertiesURL = cfg.getInitParameter("propertiesURL");}/** (non-Javadoc)* * @see* javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest* , javax.servlet.http.HttpServletResponse)*/protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;//System.out.println("已进入RandomServlet!!!");// 设置页面不缓存response.setHeader("Pragma", "No-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);// 初始化属性文件路径
//      String parentPath = request.getSession().getServletContext()
//              .getRealPath("/WEB-INF");// 产生认证原文String randNum = generateRandomNum();if (randNum == null || randNum.trim().equals("")) {System.out.println("证书认证数据不完整!");response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);return;}/*************************** 第三步 服务端返回认证原文   ***************************/// 设置认证原文到session,用于程序向后传递,通讯报文中使用//System.out.println("设置认证原文到session开始");HttpSession session = request.getSession();session.setAttribute("original_data", randNum);//System.out.println("设置认证原文到session结束");// 设置认证原文到页面,给页面程序提供参数,用于产生认证请求数据包request.setAttribute("original", randNum);// 设置跳转页面//request.getRequestDispatcher(tempURL).forward(request, response);response.getWriter().write(randNum);return;}protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws IOException, ServletException {doGet(req, resp);}/*** 产生认证原文*/private String generateRandomNum() {/*************************** 第二步 服务端产生认证原文   ***************************/String num = "1234567890abcdefghijklmnopqrstopqrstuvwxyz";int size = 10;char[] charArray = num.toCharArray();StringBuffer sb = new StringBuffer();for (int i = 0; i < size; i++) {sb.append(charArray[((int) (Math.random() * 10000) % charArray.length)]);}return sb.toString();}/*** 获取文件中的属性值*/private String getProperties(String key) {return props.get(key) == null ? null : (String) props.get(key);}
}

auth对应AuthenServlet,代码如下:

/*** Copyright © 1999-2008 JIT Co,Ltd. * All right reserved.*/
package cn.com.jit.cinas;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.XMLWriter;import sun.misc.BASE64Encoder;public class AuthenServlet extends HttpServlet {private static final long serialVersionUID = -1686835672374220173L;private String tempURL = null, propertiesURL = null;private Properties props = null;public void init(ServletConfig cfg) throws ServletException {tempURL = cfg.getInitParameter("url");propertiesURL = cfg.getInitParameter("propertiesURL");}protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;response.setCharacterEncoding("UTF-8");/**************************************************************************** isSuccess 认证是否成功,true成功/false失败;errCode 错误码;errDesc 错误描述 ** ************************************************************************///第四步:客户端认证//第五步:服务端验证认证原文//第六步:应用服务端认证//第七步:网关返回认证响应//第八步:服务端处理/************************************ 获取应用标识及网关认证地址 ************************************/boolean isSuccess = true;String errCode = null, errDesc = null;// 初始化属性文件路径String parentPath = request.getSession().getServletContext().getRealPath("/WEB-INF");// 初始化配置文件属性InputStream in = new FileInputStream(parentPath + propertiesURL);props = new Properties();props.load(in);// 可以根据需求使用不同的获取方法String appId = this.getProperties(KEY_APP_ID);String authURL = this.getProperties(KEY_AUTHURL);if (!isNotNull(appId) || !isNotNull(authURL)) {isSuccess = false;errDesc = "应用标识或网关认证地址不可为空";System.out.println("应用标识或网关认证地址不可为空\n");}String original_data = null, signed_data = null,original_jsp = null , username = null , password = null;/*************************** 获取认证数据信息 ***************************/if (isSuccess) {//System.out.println("应用标识及网关的认证地址读取成功!\n应用标识:" + appId + "\n认证地址:"+ authURL + "\n");//System.out.println("最先的原文ORIGINAL_DATA="+(String) request.getSession().getAttribute(KEY_ORIGINAL_DATA));//System.out.println("从客户端返回的原文="+(String) request.getParameter(KEY_ORIGINAL_JSP));//System.out.println("从客户的返回的认证报文="+(String) request.getParameter(KEY_SIGNED_DATA));if (isNotNull((String) request.getSession().getAttribute(KEY_ORIGINAL_DATA))&& isNotNull((String) request.getParameter(KEY_SIGNED_DATA))&&isNotNull((String) request.getParameter(KEY_ORIGINAL_JSP))) {// 获取session中的认证原文original_data = (String) request.getSession().getAttribute(KEY_ORIGINAL_DATA);// 获取request中的认证原文original_jsp = (String) request.getParameter(KEY_ORIGINAL_JSP);/*************************** 第五步:服务端验证认证原文 ***************************/if(!original_data.equalsIgnoreCase(original_jsp)){isSuccess = false;errDesc = "客户端提供的认证原文与服务端的不一致";System.out.println("客户端提供的认证原文与服务端的不一致!\n");}else{// 获取证书认证请求包signed_data = (String) request.getParameter(KEY_SIGNED_DATA);/* 随机密钥 */original_data = new BASE64Encoder().encode(original_jsp.getBytes());//System.out.println("读取认证原文和认证请求包成功!\n认证原文:" + original_jsp+ "\n认证请求包:" + signed_data + "\n");}} else {isSuccess = false;errDesc = "证书认证数据不完整";System.out.println("证书认证数据不完整!\n");}}/*************************** 第六步:应用服务端认证 ***************************/// 认证处理try {byte[] messagexml = null;if (isSuccess) {/*** 1 组装认证请求报文数据 ** 开始 **/Document reqDocument = DocumentHelper.createDocument();Element root = reqDocument.addElement(MSG_ROOT);Element requestHeadElement = root.addElement(MSG_HEAD);Element requestBodyElement = root.addElement(MSG_BODY);/* 组装报文头信息 */requestHeadElement.addElement(MSG_VSERSION).setText(MSG_VSERSION_VALUE);requestHeadElement.addElement(MSG_SERVICE_TYPE).setText(MSG_SERVICE_TYPE_VALUE);/* 组装报文体信息 */// 组装应用标识信息requestBodyElement.addElement(MSG_APPID).setText(appId);Element authenElement = requestBodyElement.addElement(MSG_AUTH);Element authCredentialElement = authenElement.addElement(MSG_AUTHCREDENTIAL);// 组装证书认证信息authCredentialElement.addAttribute(MSG_AUTH_MODE,MSG_AUTH_MODE_CERT_VALUE );authCredentialElement.addElement(MSG_DETACH).setText(signed_data);authCredentialElement.addElement(MSG_ORIGINAL).setText(original_data);// 组装口令认证信息//username = request.getParameter( "" );//获取认证页面传递过来的用户名/口令//password = request.getParameter( "" ); //authCredentialElement.addAttribute(MSG_AUTH_MODE,MSG_AUTH_MODE_PASSWORD_VALUE );//authCredentialElement.addElement( MSG_USERNAME ).setText(username);//authCredentialElement.addElement( MSG_PASSWORD ).setText(password);// 组装属性查询列表信息Element attributesElement = requestBodyElement.addElement(MSG_ATTRIBUTES);attributesElement.addAttribute(MSG_ATTRIBUTE_TYPE,MSG_ATTRIBUTE_TYPE_PORTION);// TODO 取公共信息addAttribute(attributesElement, "X509Certificate.SubjectDN","http://www.jit.com.cn/cinas/ias/ns/saml/saml11/X.509");addAttribute(attributesElement, "UMS.UserID","http://www.jit.com.cn/ums/ns/user");/*** 1 组装认证请求报文数据 ** 完毕 **/StringBuffer reqMessageData = new StringBuffer();try {/*** 2 将认证请求报文写入输出流 ** 开始 **/ByteArrayOutputStream outStream = new ByteArrayOutputStream();XMLWriter writer = new XMLWriter(outStream);writer.write(reqDocument);messagexml = outStream.toByteArray();/*** 2 将认证请求报文写入输出流 ** 完毕 **/reqMessageData.append("请求内容开始!\n");reqMessageData.append(outStream.toString() + "\n");reqMessageData.append("请求内容结束!\n");//System.out.println(reqMessageData.toString() + "\n");} catch (Exception e) {isSuccess = false;errDesc = "组装请求时出现异常";System.out.println("组装请求时出现异常");}}/***************************************************************** 创建与网关的HTTP连接,发送认证请求报文,并接收认证响应报文*****************************************************************//*** 1 创建与网关的HTTP连接 ** 开始 **/System.out.println("/*** 1 创建与网关的HTTP连接 ** 开始 **/");int statusCode = 500;HttpClient httpClient = null;PostMethod postMethod = null;if (isSuccess) {// HTTPClient对象httpClient = new HttpClient();postMethod = new PostMethod(authURL);// 设置报文传送的编码格式postMethod.setRequestHeader("Content-Type","text/xml;charset=UTF-8");/*** 2 设置发送认证请求内容 ** 开始 **/postMethod.setRequestBody(new ByteArrayInputStream(messagexml));/*** 2 设置发送认证请求内容 ** 结束 **/// 执行postMethodtry {/*** 3 发送通讯报文与网关通讯 ** 开始 **/// System.out.println("/*** 3 发送通讯报文与网关通讯 ** 开始 **/");statusCode = httpClient.executeMethod(postMethod);//  System.out.println("/*** 3 发送通讯报文与网关通讯 ** 结束 **/");/*** 3 发送通讯报文与网关通讯 ** 结束 **/} catch (Exception e) {isSuccess = false;errCode = String.valueOf(statusCode);errDesc = e.getMessage();System.out.println("与网关连接出现异常\n");}}/*****************************************************************     第七步:网关返回认证响应*****************************************************************///System.out.println("第七步:网关返回认证响应*");StringBuffer respMessageData = new StringBuffer();String respMessageXml = null;if (isSuccess) {// 当返回200或500状态时处理业务逻辑if (statusCode == HttpStatus.SC_OK|| statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR) {// 从头中取出转向的地址try {/*** 4 接收通讯报文并处理 ** 开始 **/System.out.println("/*** 4 接收通讯报文并处理 ** 开始 **/");byte[] inputstr = postMethod.getResponseBody();ByteArrayInputStream ByteinputStream = new ByteArrayInputStream(inputstr);ByteArrayOutputStream outStream = new ByteArrayOutputStream();int ch = 0;try {while ((ch = ByteinputStream.read()) != -1) {int upperCh = (char) ch;outStream.write(upperCh);}} catch (Exception e) {isSuccess = false;errDesc = e.getMessage();}if (isSuccess) {System.out.println("// 200 表示返回处理成功");// 200 表示返回处理成功if (statusCode == HttpStatus.SC_OK) {respMessageData.append("响应内容开始!\n");respMessageData.append(new String(outStream.toByteArray(), "UTF-8")+ "\n");respMessageData.append("响应内容开始!\n");respMessageXml = new String(outStream.toByteArray(), "UTF-8");} else {// 500 表示返回失败,发生异常respMessageData.append("响应500内容开始!\n");respMessageData.append(new String(outStream.toByteArray())+ "\n");respMessageData.append("响应500内容结束!\n");isSuccess = false;errCode = String.valueOf(statusCode);errDesc = new String(outStream.toByteArray());}//System.out.println(respMessageData.toString()+ "\n");}/*** 4 接收通讯报文并处理 ** 结束 **/} catch (IOException e) {isSuccess = false;errCode = String.valueOf(statusCode);errDesc = e.getMessage();//System.out.println("读取认证响应报文出现异常!");}}}/*** 1 创建与网关的HTTP连接 ** 结束 **//***************************第八步:服务端处理 ***************************/Document respDocument = null;Element headElement = null;Element bodyElement = null;if (isSuccess) {//把string转换为xmlrespDocument = DocumentHelper.parseText(respMessageXml);headElement = respDocument.getRootElement().element(MSG_HEAD);bodyElement = respDocument.getRootElement().element(MSG_BODY);/*** 1 解析报文头 ** 开始 **/if (headElement != null) {boolean state = Boolean.valueOf(headElement.elementTextTrim(MSG_MESSAGE_STATE)).booleanValue();if (state) {isSuccess = false;errCode = headElement.elementTextTrim(MSG_MESSAGE_CODE);errDesc = headElement.elementTextTrim(MSG_MESSAGE_DESC);//System.out.println("认证业务处理失败!\t" + errDesc + "\n");}}}if (isSuccess) {//System.out.println("解析报文头成功!\n");/* 解析报文体 */// 解析认证结果集Element authResult = bodyElement.element(MSG_AUTH_RESULT_SET).element(MSG_AUTH_RESULT);isSuccess = Boolean.valueOf(authResult.attributeValue(MSG_SUCCESS)).booleanValue();if (!isSuccess) {errCode = authResult.elementTextTrim(MSG_AUTH_MESSSAGE_CODE);errDesc = authResult.elementTextTrim(MSG_AUTH_MESSSAGE_DESC);//System.out.println("身份认证失败,失败原因:" + errDesc);}}if (isSuccess) {//System.out.println("身份认证成功!\n");// 解析用户属性列表Element attrsElement = bodyElement.element(MSG_ATTRIBUTES);if (attrsElement != null) {List attributeNodeList = attrsElement.elements(MSG_ATTRIBUTE);for (int i = 0; i < attributeNodeList.size(); i++) {Element userAttrNode = (Element) attributeNodeList.get(i);String name = userAttrNode.attributeValue(MSG_NAME);String value = userAttrNode.getTextTrim();request.setAttribute(name, value);//System.out.println("属性名:" + name + "\t属性值:" + value//   + "\n");//this.password = value;this.getUsername(value);}}}} catch (Exception e) {isSuccess = false;errDesc = e.getMessage();}if (!isSuccess) {if (isNotNull(errCode)) {request.setAttribute("errCode", errCode);}if (isNotNull(errDesc)) {request.setAttribute("errDesc", errDesc);}System.out.println("处理数据结束,业务处理失败,失败原因:" + errDesc + "\n");}else {System.out.println("处理数据结束,一切正常!\n");}request.setAttribute("isSuccess", new Boolean(isSuccess).toString());//request.getRequestDispatcher(tempURL).forward(request, response);if(isSuccess){          response.getWriter().write("success,"+this.username+","+this.realname);}else{response.getWriter().write("failure,"+errCode+","+errDesc);  }}private void getUsername(String value) {String[] users = value.split(",");String usercodeTemp= users[0].trim();String usernameTemp = users[1].trim();this.realname = usercodeTemp.substring(usercodeTemp.indexOf('=')+1, usercodeTemp.length());this.username = usernameTemp.substring(usernameTemp.indexOf('=')+1, usernameTemp.length());}protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws IOException, ServletException {doGet(req, resp);}/*** 判断是否是空串*/private boolean isNotNull(String str) {if (str == null || str.trim().equals(""))return false;elsereturn true;}/*** 获取文件中的属性值*/private String getProperties(String key) {return props.get(key) == null ? null : (String) props.get(key);}/*** 向xml插入结点*/private void addAttribute(Element attributesElement, String name,String namespace) {Element attr = attributesElement.addElement(MSG_ATTRIBUTE);attr.addAttribute(MSG_NAME, name);attr.addAttribute(MSG_NAMESPACE, namespace);}/******************************* 报文公共部分 ****************************//** 报文根结点 */private final String MSG_ROOT = "message";/** 报文头结点 */private final String MSG_HEAD = "head";/** 报文体结点 */private final String MSG_BODY = "body";/** 服务版本号 */private final String MSG_VSERSION = "version";/** 服务版本值 */private final String MSG_VSERSION_VALUE = "1.0";/** 服务类型 */private final String MSG_SERVICE_TYPE = "serviceType";/** 服务类型值 */private final String MSG_SERVICE_TYPE_VALUE = "AuthenService";/** 报文体 认证方式 */private final String MSG_AUTH_MODE = "authMode";/** 报文体 证书认证方式 */private final String MSG_AUTH_MODE_CERT_VALUE = "cert";/** 报文体 口令认证方式 */private final String MSG_AUTH_MODE_PASSWORD_VALUE = "password";/** 报文体 属性集 */private final String MSG_ATTRIBUTES = "attributes";/** 报文体 属性 */private final String MSG_ATTRIBUTE = "attr";/** 报文体 属性名 */private final String MSG_NAME = "name";/** 报文体 属性空间 */private final String MSG_NAMESPACE = "namespace";/*********************************************************************//******************************* 请求报文 ****************************//** 报文体 应用ID */private final String MSG_APPID = "appId";/** 报文体 认证结点 */private final String MSG_AUTH = "authen";/** 报文体 认证凭据 */private final String MSG_AUTHCREDENTIAL = "authCredential";/** 报文体 detach认证请求包 */private final String MSG_DETACH = "detach";/** 报文体 原文 */private final String MSG_ORIGINAL = "original";/** 报文体 用户名 */private final String MSG_USERNAME = "username";/** 报文体 口令 */private final String MSG_PASSWORD = "password";/** 报文体 属性类型 */private final String MSG_ATTRIBUTE_TYPE = "attributeType";/** 指定属性 */private final String MSG_ATTRIBUTE_TYPE_PORTION = "portion";/*********************************************************************//******************************* 响应报文 ****************************//** 报文体 认证结果集状态 */private final String MSG_MESSAGE_STATE = "messageState";/** 响应报文消息码 */private final String MSG_MESSAGE_CODE = "messageCode";/** 响应报文消息描述 */private final String MSG_MESSAGE_DESC = "messageDesc";/** 报文体 认证结果集 */private final String MSG_AUTH_RESULT_SET = "authResultSet";/** 报文体 认证结果 */private final String MSG_AUTH_RESULT = "authResult";/** 报文体 认证结果状态 */private final String MSG_SUCCESS = "success";/** 报文体 认证错误码 */private final String MSG_AUTH_MESSSAGE_CODE = "authMessageCode";/** 报文体 认证错误描述 */private final String MSG_AUTH_MESSSAGE_DESC = "authMessageDesc";/*********************************************************************//**应用数据库用户名**/private String username;/**应用数据库真实姓名**/private String realname;/**应用数据库密码**/private String password;/**************************** 业务处理常量 ****************************//** 认证地址 */private final String KEY_AUTHURL = "authURL";/** 应用标识 */private final String KEY_APP_ID = "appId";/** session中原文 */private final String KEY_ORIGINAL_DATA = "original_data";/** 客户端返回的认证原文,request中原文 */private final String KEY_ORIGINAL_JSP = "original_jsp";/** 证书认证请求包 */private final String KEY_SIGNED_DATA = "signed_data";/*********************************************************************/
}

代码显得有些繁琐冗余,不花费一定量的时间是无法真正掌握的,这是吉大正元给的demo,没有经过大的改动直接拿来用了。需要注意以下几点:

1,需要在服务器上配置和应用相关的ID,用于识别不同的应用。

2,需要安装吉大正元自带的驱动程序,否则无法识别key盘,还要使用object标签加载一个动态链接库,如上:

<object classid="clsid:707C7D52-85A8-4584-8954-573EFCE77488"
    id="JITDSignOcx" width="0" codebase="/${res}/jit/JITDSign.cab#version=2,0,24,18"></object>

为了加载一个类,JITDSign可以直接使用类里面的方法。

3,在进行ajax提交的时候注意保持同步,否则可能出现不按顺序执行的情况。

关于文档和demo可以到http://115.com/file/c2gqtrxh下载。

CA认证——使用吉大正元认证系统为门户把关相关推荐

  1. trs ids身份服务器系统实现统一身份认证与单点登录平台技术,统一身份认证和单点登录系统建设方案.pdf...

    福建省公安公众服务平台 统一身份认证及单点登录系统建设方案 福建公安公众服务平台建设是我省公安机关 "三大战役"社会管 理创新的重点项目之一: 目前平台目前已经涵盖了公安厅公安门户 ...

  2. tomcat实现https双向认证(在win10系统使用jdk1.8自带工具keytool)

    tomcat实现https双向认证(在win10系统使用jdk1.8自带工具keytool) 以下操作我在D:\shiro-cas-ssl进行操作 使用win+R运行certmgr.msc可以查看证书 ...

  3. 华为 H3C 配置 Portal认证 mac-trigger快速认证 Mac无感知认证 Radius认证计费 对接 外部Portal认证计费系统 案例

    华为 H3C 配置 Portal认证 mac-trigger快速认证 Mac无感知认证 Radius认证计费 对接 外部Portal认证计费系统 案例 介绍: OpenPortal网络准入认证计费系统 ...

  4. CCF CSP认证考试在线评测系统

    关于CCF CSP认证考试在线评测系统 CCF CSP认证考试简介 CCF是中国计算机学会的简称.CCF计算机软件能力认证(简称CCF CSP认证考试)是CCF于2014年推出,是CCF计算机职业资格 ...

  5. 人脸识别系统做CCC认证,人脸识别系统做SRRC认证

    人脸识别系统做CCC认证,人脸识别系统做SRRC认证 人脸识别一体机3C认证办理流程 1:认证委托和申请,资料必须纸档并签字,盖公司印章,一式两份. 2:产品送样检测,每个产品成品数量为五,收到测试样 ...

  6. 双因子身份认证如何保障 Windows 系统登录安全?

    密码作为最常用的安全措施,在云时代的 IT 环境中似乎难以应对.近年来的安全漏洞表明,单靠密码本身并不足以抵御网络攻击.事实上,凭证泄露已经成为企业最核心的安全威胁之一.为了保证企业账户安全和登录安全 ...

  7. 登陆验证发展史(cookie认证->session认证->token认证->JWT,单系统登陆->多系统单点登陆)

    登陆验证发展史有两条主线.在服务部署方式层面,早期的Web服务系统简单一般都是单系统,登陆的话就登陆这一个系统就好了,随着系统复杂性越来越高,一个大的系统往往由很多子系统组成,用户使用这个大系统时不可 ...

  8. 华为 配置 MAC认证优先 Portal认证 Mac无感知快速认证 Radius认证计费 对接 外部 Portal认证计费系统 案例

    华为 配置 MAC认证优先 Portal认证 Mac无感知快速认证 Radius认证计费 对接 外部 Portal认证计费系统 案例 介绍: OpenPortal网络准入认证计费系统,支持用户名密码认 ...

  9. SSL/TLS单向认证和双向认证介绍

    为了便于理解SSL/TLS的单向认证和双向认证执行流程,这里先介绍一些术语. 1. 散列函数(Hash function):又称散列算法.哈希函数,是一种从任何一种数据中创建小的数字"指纹& ...

最新文章

  1. logback配置文件
  2. Windows Embedded Compact 7新特性
  3. Win32字符串处理函数
  4. 设计模式之_Iterator_03
  5. python函数对变量的作用_python函数局部变量用法
  6. C++ 多字节与宽字符串的相互转换
  7. springboot 2.0 Redis command timed out的解决
  8. matlab虚拟现实之V-Realm Builder2特别组节点使用
  9. 优秀!26岁任985大学博导!
  10. jersey创建restful服务及调用_Jersey实现Restful服务(实例讲解)
  11. CentOS8下vi编辑器常用命令
  12. Django开发教程 第一节 HelloWorld
  13. 一起玩react 你不知道的setState
  14. PageOffice实现在线编辑Word的手写批注功能
  15. 【OpenCV】漫水填充
  16. 【操作系统】实验六 系统内存使用统计
  17. Simulink简单模型
  18. html行间距属性,css行间距属性
  19. python-docx 不改变原文件调整段落行间距的问题
  20. GEA 3.1 重温C++以及实践

热门文章

  1. 基于树莓派的空气监测系统(1)项目介绍
  2. 华硕X550高性价比
  3. 基于react + redux + ES6 + webpack + react-router的英雄联盟战绩查询应用
  4. 【系统集成项目管理工程师】—挣值管理
  5. 【开箱即用】vk-uniCloud-router - 云函数路由模式 - uniCloud企业级快速开发框架
  6. 2020第十一届蓝桥杯C/C++ 省赛A组 题解
  7. 在ubuntu中设置使用网络摄像头
  8. 有时候一个人的追求是刻在骨子里的。
  9. 零基础学数据分析,需要掌握哪些技能
  10. 百度UEditor在线编辑器