Cognos 8.3用户权限控制入门

    学习Cognos 8.3入门中,需要实现Cognos与现有业务系统集成,尤其是用户权限部分。官方文档及网上的教程对Cognos用户权限控制的实现机制都语焉不详,迫切需要一个快餐式的Step-By-Step的学习文档。整理一下学习的东西,希望对新手们有所帮助。

    目的:

    1. 采用OpenDS存储组织机构及用户信息,实现OpenDS与Cognos集成

    2. 使用Cognos Framework Manager来实现用户数据过滤控制,实现同一报表用户只能够看见自己的数据

    3. 二次开发实现cognos与业务系统的用户数据集成

  下载《Cognos 8.3用户权限控制入门》

 

Technorati 标签: ,,,,

站内标签:

电子商务平台之“推荐作为服务”

    在亚马逊这样的电子商务标杆企业的示范下,推荐系统对于电子商务网站的价值已被大家所认同,例如:增加网站的访问量,提升销售额;提高网站的交叉销售能力;增加顾客在网店上的停留时间,浏览更多的商品;将网站的浏览者转变为购买者等等。因此大家都希望能够拥有自己的推荐系统。

    但相对于网站开发技术而言,推荐系统由于涉及数据仓库、数据挖掘、统计分析、人工智能等相关技术,因此技术门槛要高得多,对于研发能力相对较弱的中小型的企业而言,要自己研发推荐系统难度很大。于是乎诞生了一些以“推荐作为服务”(Recommendation as a Service)的公司。

1、推荐服务的基本模式

    这些公司拥有推荐系统核心技术,通过SaaS模式对外提供推荐服务,一般的服务方式如下:

    1)、以接口、批量上传等形式导入合作伙伴的产品目录

    2)、在合作伙伴网站页面嵌入用于跟踪用户行为的javascript脚本

    3)、通过对诸如商品信息、历史用户数据、用户行为(包括搜索、网站点击行为、购买历史、喜好、购物车、收藏历史)等行为数据的汇总分析,建立网站相应的推荐模型

    4)、用户登录网站时候,根据用户历史行为数据实时分析预测用户的喜好,产生个性化推荐。

    下图摘自StrandsMybuys 公司的业务流程图,基本上概括了推荐服务的核心模型

recommendation engine,推荐引擎,推荐系统,协同过滤,开放平台,推荐作为服务,recommendation as a service

                                                 Strands的模型

 

recommendation engine,推荐引擎,推荐系统,协同过滤,开放平台,推荐作为服务,recommendation as a service

                                                    Mybuys 的模型

    尽管推荐服务核心算法的理论基础基本上类似,但不同行业推荐对象对应的模型不尽相同(例如电子商务、SNS社区、媒体站点),更为重要的是由于各公司商业模式的不同,不同的公司对于推荐服务有不同的要求,因此推荐服务提供商针对不同行业及不同公司所采用推荐算法及模型实现都会有所不同。   

2、推荐服务提供商

   2.1、国外的“推荐作为服务”提供商:

    StrandsMybuysBaynoteLoomiaAggregrate KnowledgeRichRelevanceOutBrainATGAvail IntelligenceCertona、    ChoicestreamApture

recommendation engine,推荐引擎,推荐系统,协同过滤,开放平台,推荐作为服务,recommendation as a service 

 

2.2、国内的“推荐作为服务”提供商:

    百分点麦路

    麦路最初以“推荐作为服务”作为商业模式,目前重点已经转向运营购物返现联盟发现宝

    而百分点仍然专注在“推荐作为服务”上,相对于麦路更加专业,百分点推荐技术研究中心及电子期刊收集了一些有价值的资料。尽管作为纯技术驱动的公司在国内现实的商业环境下生存相对较难,但随着国内电子商务的繁荣及成熟,相信像百分点这样专业化的公司会有美好的前景。

3、几点思考:

3.1、“推荐作为服务”的商业模式

    1)、独立的推荐服务提供商

    2)、依托于某个电子商务开放平台(例如淘宝开放平台)、SNS开放平台提供推荐服务

    3)、依托于广告联盟

    4)、依托于网络营销、购物返现联盟

    5)、依托于行业垂直搜索引擎公司

    电子商务、SNS社区等互联网新兴应用的高速发展,对个性化推荐的需求越来越强烈,因此那些专注于“推荐作为服务”这一领域的推荐服务提供商会有较大的成长空间,尽管尚有很长的路要走。

   “推荐作为服务”的一种趋势是多种模式的结合,尤其是与开放平台、网络营销联盟、搜索引擎多种模式的结合,因此“推荐作为服务”提供商最终可能变成网路营销服务提供商、垂直搜索引擎公司、广告媒体公司等等。

3.2、、“推荐作为服务”的核心价值

    “推荐作为服务”提供商拥有的最为核心财富不是推荐技术本身,而是通过推荐服务所积累的海量数据,特别是用户数据和项目(item)数据。这正如Google自身最核心的财富不是搜索引擎本身,而是对于用户点击流数据。因此从这点来说,“推荐作为服务”最大的实践者其实是Google。

    用户数据:当下的“推荐作为服务”提供商基本上都围绕一个应用或一个平台来提供服务,并没有以用户网络身份标识为中心来整合各种用户行为数据。如果能够借助opensocial、openid、oauth等开放协议整合用户的网络身份,获得用户各种网络活动的数据,为用户提供更加个性、精准、实时的推荐服务,这样的推荐服务对用户极大的使用价值。

    项目数据:所谓的项目(item)数据的内涵可以是电子商务平台的商品,可以是社会化媒体的一个视频、一篇blog,可以是搜索引擎的搜索关键词,而这些恰恰是那些传统的电子商务、搜索引擎、广告巨头们的关注点。但这并不意味着“推荐作为服务”提供商无法与这些巨头们竞争。“推荐作为服务”之所以能够蓬勃发展,正说明了目前的巨头们所提供的服务在这些领域并不能很好满足用户的需求。例如在实时网络(Real-Time)、开放平台等领域。

    对于用户而言,推荐服务最核心的价值在于更加个性化、精准、实时的推荐,因此推荐服务未来的趋势之一是对用户身份及数据的整合。

    对于众多的中小企业而言,推荐服务最核心的价值在于能够帮助其带来流量、促成交易、创造交易,因此推荐服务未来的趋势之一应该是与网络营销、广告联盟等服务更加的紧密结合。

3.3、“推荐作为服务”的最佳实践

    Strands 的Francisco Martin 在RecSys 2009上的演讲 RecSys 2009 Keynote: Top 10 Lessons Learned Developing, Deploying, and Operating Real-World Recommender Systems 分享了Strands在此方面的经验,很精彩:

  • Lesson 1. Make sure a recommender is really needed! Do you have lots of recommendable items? Many diverse customers?… also think Return-on-Invesment… a more sophisticated recommender may not deliver a better ROI.
  • Lesson 2. Make sure the recommendations make strategic sense. Is the best recommendation for the customer also the best for the business? What is the difference between a good and useful recommendation? Good recommendations vs useful recs; obvious recommendations may not be useful; risky recs may deliver better long-term value.
  • Lesson 3. Choose the right partner! Select the right rec vendor vs hire some #recsys09 students. If you are a big company the best thing you can do is organize a contest.
  • Lesson 4. Forget about cold-start problems (!) …. just be creative. The internet has all the data that you need (somewhere…).
  • Lesson 5. Get the right balance between data and algorithms. 70% of the success of a recommendation system is in the data, the other 30% in the algorithm.
  • Lesson 6. Finding correlated items is easy but deciding what, how, and when to present them to the user is hard… or don’t just recommend for the sake of it. Remember, user attention is a scarce and valuable resource. Use it wisely! … dont make a recommendations to a customer who is just about to pay for items at the checkout! User interface should get at least 50% of your attention.
  • Lesson 7 Don’t waste time computing nearest neighbours (use social connections)… just mine the social graph. Might miss useful connections?
  • Lesson 8 Don’t wait to scale!
  • Lesson 9: Choose the right feedback mechanism. Stars vs thumbs …. the YouTube problem. More research on implicit and other feedback mechanisms is needed. The perfect rating system is no rating system! … focus on the interface.
  • Lesson 10 Measure Everything! … business control and analytics is a big opportunity here.

 

4、参考资料

  RecSys 2009 Keynote: Top 10 Lessons Learned Developing, Deploying, and Operating Real-World Recommender Systems

  5 Problems of Recommender Systems

  Readwriteweb series on recommendation technologies

  Baynote, Strands, RichRelevance — will they survive the “recommendation engine” consolidation?

 


站内标签:

电子商务平台之平台服务杂思

    在去哪儿上买3张成都到北京的机票,一张儿童票、2张成人票。比价后,选择了一家价格较为便宜的分销商下单,跳转到分销商的网站下单时候成人票860,儿童票720,加上保险、机场建设费等费用,总价2622元。做支付时候也没具体留意总的支付金额(呵呵,是够粗心的),完成支付后,等待交易成功的通知。过了2个小时还没有收到短信通知,于是打分销商的客服电话,打了10多次,一直是忙音,语音始终提示前面有2–8人等待。于是上分销商的网站看订单状态。由于不知道初始密码,通过重置密码方式,接近10多分钟都没收到重置短信。后来按照111111、2222222、333333顺序方式测密码,终于登陆进去了。发现订单发现每张成人票的支付金额为1080元,而且订单中出现了四张成人票记录。好在总价中只计算了两张票的价格。总价为3062元。

    再打电话投诉,仍然一直是忙音。打了2个多小时,打了30多个电话后,终于打通了。把情况一说,客服人员很流利地说明了原因:他们自己系统是有问题,与去哪儿合作的合作页不是实时刷新的,因此在下单时候成人票的价格在他们平台上是1080,而不是860元,要避免此种情况,最好在下单前在他们平台再查询一下实时价格。从客服的解释来看,以前应该也遇见很多这样的问题,很奇怪明知有问题,为何一直不修改,只好退票。退票时候,客服人员问银行账号,而且建议最好是工行的账号。很奇怪,问她:不是通过快钱支付的吗,你直接给我退回我的支付行就行了。客服说不行,如果不用工行而用其他银行账号,退款退回时间不确定。

    懒得再一家一家地比较,担心再出问题,于是直接在去哪儿上比较了一下进行直销的航空公司的价格,找了相对便宜的南方航空下了单。在这过程中,暴露了很多问题,包括:

    1、合作商户系统与平台对接时候信息同步、实时性问题

    2、合作商户系统本身存在很多问题

    3、合作商户本身服务的能力、服务规范性及服务质量

    4、平台服务体验的一致性问题

    5、平台对合作商户资质的选择

    这些问题归根结底可以概括为电子商务平台服务问题,以上问题能否有效解决影响着一个电子商务平台的成败,总结一下零碎思考的一些内容:

1、平台服务的边界

   对用户而言,在购买机票过程中涉及两个比较大的电子商务平台:去哪儿的机票比价平台、快钱的支付平台。在两个平台作为这些商户的平台服务提供商,理论上只需要能够为这些商户提供好所需要的各种服务就行,合作商户以上的各种问题让合作商户自己搞定就行,不能归结为平台的问题。

   但对于最终用户而言,在使用服务过程中出现的各种问题都是平台的问题,他并很不清楚这些系统的边界,他只关心能够通过平台低成本、便捷、安全享受各种服务。如果合作商户不能为客户提供优质的服务,那平台本身的价值也打了很大的折扣。平台要保证服务的一致性,要维护平台核心的价值,就应该树立平台的服务标准,用这些标准来要求商户并帮助合作商户从各个层面上进步。合作商户的高度决定了平台的高度。

    因此作为一个平台本身,在考虑平台建设时候,我们不应当只是盯住平台本身的边界,平台的边界的划分应该以用户视角来看,以保证用户以一致性的体验完成整个购物过程。这就要求平台的合作商户的选择、合作商户服务能力、合作商户系统等问题上必须以平台化的要求来执行,对达不到平台化要求的,或者帮助其进步、或者淘汰。   

2、平台服务的核心价值

    对于合作商户而言,如果平台只是单纯作为一个销售通路或营销通路,那平台给合作商户带来的价值并不是持久性的,可替代性很高。尤其航空公司们的直销业务在整个机票分销业务中比重愈来愈大的情况下,这些合作商户凭什么生存呢?

    这些平台服务提供商肯定不希望合作商户在航空公司们的电子商务直销浪潮下消亡掉,在平台上面只剩下几个有限的几个航空公司。平台合作商户的多样化、差异化才能够保证平台对于最终用户的吸引力,也才能够保证平台持久存在的价值。

    在面临日益剧烈的竞争下,平台服务对于合作商户的核心价值在于:通过平台来帮助其提高竞争力。这种竞争力包括服务能力、盈利能力、营销能力、服务的持久性等。

  


站内标签:

从Evernote看产品竞争策略

    Please, Evernote, wake up. I wanted you to win. 这篇文章不错,虽然只是谈论Evernote与Onenote的竞争策略,但对于产品管理而言,有太多的值得思考借鉴的。作者认为Evernote在过去2年多,丧失了众多的超越Onenote的机会。

    如果我是Evernote的产品经理,我会怎么做呢?总结一下文章的思路:

1、聚焦核心定位:

    相对于Onenote,Evernote作为一个尾随者,在市场影响力及可以利用的资源上都无法与Onenote相匹敌。因此首先最重要的是要时刻遵循自己区隔于Onenote的核心定位:"Notes rethought in Web 2.0"。要找到自己区隔于竞争对手的产品定位很容易(什么定位理论、竞争分析、蓝海理论等满大街烂遍的理论都能够完成),最难的莫过于对产品定位信仰般的坚持,莫过于在定位下对产品功能取舍的平衡及度的把握,莫过于在小有成就后能够压抑住自己进行产品延伸的冲动。

2、改变游戏规则:

    要在与Onenote的竞争中占领上风,依靠比拼功能及用户体验的方式并不能颠覆竞争的格局。一个有效的策略就是所谓的“颠覆性创新”,既然Onenote是收费的、闭源、封闭的,那Evernote可以通过开放平台、Open Source、免费方式来改变游戏规则,让对手不得不放弃其业务核心来遵循你的游戏规则及节奏。Google的「比免费更便宜」的商业模式 可以说是当下最为经典的案例。

3、“抄越”竞争对手:

    有一个强大的竞争对手有时候其实也是一种福气,至少说明市场的价值、机会以及事业的意义。强大的竞争对手是最好的老师,在聚焦核心定位、改变游戏规则的前提下,认真研究学习、抄袭竞争对手优秀的产品功能、用户体验、设计思想,山寨化之并超越之(谓之“抄越”)。虽然我们都在研究竞争对手的产品,但我们缺少对于强大竞争对手的“战略上的藐视,战术上的重视”,更多时候只是处于藐视或自卑的状态,因此基本上只是停留在功能copy层面,并没有用心去领会竞争对手产品的核心设计思想,因此所谓的“抄越”也就无从谈起。

    正如文章所说:I’m hoping Evernote wakes up, assigns at least one developer full-time to analyze what OneNote did right in usability, run their own usability tests with students, and get Evernote to be the best client-side note-taking experience in the world.

4、集中优势资源打歼灭战:

   要集中优势资源对核心产品功能(包括用户体验)进行研发并做到极致,不要将宝贵的资源投到非核心的功能完善上去。产品有了自己的核心优势后才可能有机会将游戏继续下去,“少即是多”。  

5、更加注重与用户的互动,倾听用户的声音

   对Evernote而言,拥有这样忠实且专业的用户是最为宝贵的资源,希望Evernote真的能够醒醒倾听用户的心声。

   通过与用户的互动及对用户的运营,可以获得第一手的用户需求,保证产品竞争策略的有效性。其实任何产品都有这样用户,只不过很多时候我们太过于自负或是过于忙碌,而最终忘记了产品最终的用户是谁。

   写到一半才发现这些道理大家都知道的,懒得写下去了。可为何一家又一家的公司都在犯着同样的错误呢?“纸上得来终觉浅 绝知此事要躬行”。


站内标签:

使用CAPICOM实现证书管理

    在基于ejbca搭建CA时候,需要实现如下功能:

    1)、在客户端实现对页面关键数据(例如订单金额等)采用签名、数字信封等方式进行加密

    2)、能够较好支持USB KEY集成

    3)、用户申请数字证书导入浏览器后,能够通过Web页面对浏览器证书进行重新申请(renewal)、删除、显示、查询、验证等功能

    单独依靠XEnroll.dll或CertEnroll.dll控件已经无法满足以上要求。微软的CAPICOM组件封装了Windows CryptAPI的各种操作,可以在Windows环境下各种语言中使用。而且CAPICOM中的大多数接口都是“脚本安全”的,可以直接在网页脚本中安全使用CAPICOM接口所提供的功能。

    需求1)、2)的实现思路:在前台利用CAPICOM组件读取浏览器或USB盘中的用户证书,对页面表单的关键数据进行SHA1签名。将签名后的密文与页面表单中的明文提交到服务器端。服务器从用户请求密文解密得到用户证书及页面关键数据的摘要(利用Bouncycastle、Apache Commons Codec),验证证书的合法性及有效性。然后对提交的页面明文计算SHA1,把得到的结果与从密文是解出摘要进行对比,从而实现数据完整性的校验。

    需求3)的实现思路:关键是要实现证书的删除、查询、验证功能,结合IE中自动安装用户数字证书 IE中自动安装根数字证书 ,可以很容易实现相关功能。

  CAPICOM中常用的类主要包括:StoreCertificatesCertificate 

  基本操作步骤为:创建Store对象->打开Store对象->查找需要操作的证书集合(Certificates)->对单个证书(Certificate)进行操作

 

1、一个简单例子:

<OBJECT id="capicom" codeBase="http://download.microsoft.com/download/E/1/8/E18ED994-8005-4377-A7D7-0A8E13025B94/capicom.cab#version=2,0,0,3" classid="clsid:A996E48C-D3DC-4244-89F7-AFA33EC60679" VIEWASTEXT>
</OBJECT>
<script language="javascript">
var CAPICOM_CURRENT_USER_STORE = 2
var CAPICOM_MY_STORE = "My"
var CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1
var CAPICOM_STORE_OPEN_READ_WRITE=1
var myStore = new ActiveXObject("CAPICOM.Store");
myStore.Open(CAPICOM_CURRENT_USER_STORE,CAPICOM_MY_STORE,CAPICOM_STORE_OPEN_READ_WRITE);
var myStoreCerts = myStore.Certificates;
var info="";
for(i = 1; i<= myStoreCerts.Count; i++)
{            info+=    " Subject Name : "+myStoreCerts.Item(i).SubjectName +"<br/>";
}
document.write(info);
</script>

 

2、一个更复杂的例子:

2.1)、capicomtest.html

<html>
<head>
<title>CAPICOM使用DEMO</title>
<meta http-equiv="no-cache">

</head>
<body onLoad="listCert()">
    <OBJECT id="capicom" codeBase="http://download.microsoft.com/download/E/1/8/E18ED994-8005-4377-A7D7-0A8E13025B94/capicom.cab#version=2,0,0,3" classid="clsid:A996E48C-D3DC-4244-89F7-AFA33EC60679" VIEWASTEXT>
    </OBJECT>
<script language="javascript" src="capicom.js"></script>
<form name="frmStore" method="post" action="">
  1.读取用户证书
    <br>
    <br>
  证书类型:
  <select id="storeName" size="1" name="storeName">
      <option value="my" selected>Personal</option>
      <option value="root">Root</option>
      <option value="AddressBook">Address Book</option>
      <option value="ca">CA</option>
  </select>
  <input type="button" value="获取证书列表" onclick="listCert()">
  </p>
  <p>选择一个证书:<br>
    <select id="allCerts" size="10" name="allCerts" >
    </select>
    <br>
    <input id="delcert" type="button" name="delcert" value="删除选定证书" onclick="deleteCert()" />
        <input id="verifydate" type="button" name="verifydate" value="验证选定证书有效期" onclick="alert(verifyCertValidDate())" />

</form>
</body>
</html>

   

 

2.2)、capicom.js

var CAPICOM_CURRENT_USER_STORE = 2
var CAPICOM_MY_STORE = "My"
var CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1
var CAPICOM_STORE_OPEN_READ_WRITE=1

var myStore = new ActiveXObject("CAPICOM.Store");
myStore.Open(CAPICOM_CURRENT_USER_STORE,CAPICOM_MY_STORE,CAPICOM_STORE_OPEN_READ_WRITE);      

function deleteCert()
{
    var myStore = new ActiveXObject("CAPICOM.Store");
    try{

          var storeName = frmStore.storeName.options(frmStore.storeName.selectedIndex).value;
            myStore.Open(CAPICOM_CURRENT_USER_STORE,storeName,CAPICOM_STORE_OPEN_READ_WRITE);

            var index = frmStore.allCerts.options.selectedIndex;
            var cert = frmStore.allCerts.options[index].value;
          subjectName=getCertCN(cert);

            var myStoreCerts = myStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, subjectName, true);
             for(i = 1; i<= myStoreCerts.Count; i++)
            {
                     if(myStoreCerts.Item(i).HasPrivateKey()){
                         //要删除用户证书,首先要删除私钥,才能够调用Certificates.Remove方法删除证书
                         myStoreCerts.Item(i).PrivateKey.Delete();
                     }

                 myStore.Remove(myStoreCerts.Item(i));
            }
            alert("删除证书成功");
            myStoreCerts=null;
            myStore.Close() ;
            myStore=null;    

    }catch(e){
        alert("删除证书失败,错误码为:"+e.number);

    }
    window.location.reload();
}

function verifyCertValidDate(){
    var myStore = new ActiveXObject("CAPICOM.Store");

 try{
         var storeName = frmStore.storeName.options(frmStore.storeName.selectedIndex).value;
        myStore.Open(CAPICOM_CURRENT_USER_STORE,storeName,CAPICOM_STORE_OPEN_READ_WRITE);
    }
    catch (e)
    {
        alert("打开证书库失败");
        return ;
    }
    var index = frmStore.allCerts.options.selectedIndex;
    var cert = frmStore.allCerts.options[index].value;
  subjectName=getCertCN(cert);

  var myStoreCerts =  myStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, subjectName, true);
    var result="";

    for(i = 1; i<= myStoreCerts.Count; i++)
    {
        var validToDate=new Date(myStoreCerts.Item(i).ValidToDate+"");
        var currentDate=new Date();
        var diff=(validToDate-currentDate)/(3600*24*1000);

        if(diff >31){
            result="证书"+myStoreCerts.Item(i).subjectName+" 有效期为:"+formatDate(validToDate);
        }
        else if(diff<=31 && diff >0){
            result="证书"+myStoreCerts.Item(i).subjectName+" "+diff+"后即将过期,请更新证书";
                alert(result);
            return result;
        }
        else{
                result="证书"+myStoreCerts.Item(i).subjectName+" 已经过期,请更新证书";
                    alert(result);
                return result;
        }
    }
    if(result=="")
        return "没有有效期";
    return result;

}

function listCert()
{
    var myStore = new ActiveXObject("CAPICOM.Store");
    try
    {
        var storeName = frmStore.storeName.options(frmStore.storeName.selectedIndex).value;
        myStore.Open(CAPICOM_CURRENT_USER_STORE, storeName, CAPICOM_STORE_OPEN_READ_WRITE);
    }
    catch (e)
    {
        alert("打开证书库失败");
        return false;
    }    

    var count = frmStore.allCerts.options.length;
    for (i = 1; i <= count; i++)
    {
        frmStore.allCerts.options.remove(count-i);
    }
    while (frmStore.allCerts.options.length) frmStore.allCerts.options[0] = null;    

    //只列出DN中有yeeach.com的证书
    var myStoreCerts = myStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, "yeeach.com", true);
    for(i = 1; i<= myStoreCerts.Count; i++)
    {
         var certInfo = new Option("cert: " + myStoreCerts.Item(i).subjectName );
         certInfo.value=myStoreCerts.Item(i).subjectName ;
        frmStore.allCerts.options.add(certInfo, i);
    }
}

function getCertCN(dn){
    //对于CAPICOM_CA_STORE、CAPICOM_OTHER_STORE、CAPICOM_ROOT_STORE不适用,需要调整
        i=dn.indexOf('CN=');
    if(i==-1){
        return "没有CN";
    }else{
            cn=dn.substr(i+3);
            return cn;
    }
}

function formatDate(inputDate){
    if(null == inputDate){
        return "";
    }
    //var year = 1900+date.getYear();
        var year = inputDate.getYear();
    var month = inputDate.getMonth()+1;
    if(month < 10) month = "0"+month;

    var day = inputDate.getDate();
    if(day < 10) day = "0"+day;

    var hour = inputDate.getHours();
    if(hour < 10) hour = "0"+hour;
    var minute = inputDate.getMinutes();
    if(minute < 10) minute = "0"+minute;
    var second = inputDate.getSeconds();
    if(second < 10) second = "0"+second;
    return year+"-"+month+"-"+day;
}

 

测试代码打包下载

 

3、参考文档:

CAPICOM Reference

How to use Java produce Signature by USBKey under CryptoAPI/CSP

How to create a digital signing solution with only JavaScript

How to obtain signer’s details from a JavaScript signed data

Automatic sign of a text in with a web script using CAPICOM with an ActiveX

数字证书在WEB应用中登录

 


站内标签:

IE中自动安装用户数字证书

    在基于ejbca搭建数字证书时候,需要实现用户自助申请数字证书(Certificate signing request)并自动安装到IE浏览器中的功能(Certificate enrollment)。

    相关的资料极其缺少,好在ejbca中有相关的例子可以参考,尽管不是很完整。整理一下研究的大致成果。

1、基本思路:

    1)、Certificate signing request(CSR)

     证书签发请求(CSR),也叫做证书请求,是从请求者浏览器发送到证书中心来申请一个数字身份证书的一条信息,在公共密钥基础架构系统中。在创建一个 CSR 之前,这个请求者首先产生一个密钥对,为这个私有密钥保密。CSR 包括鉴别请求者一条的信息,和由这个请求者选择的公共密钥。相应的私有密钥不包含在 CSR 中,但是被用于数位签名整个请求。

    在XP、Windows 2003的IE上,通过XEnroll.dll控件的createPKCS10方法来生成CSR(Certificate signing request)。

   在Vista,Windows 2008,Windows 7 的IE上,需要使用CertEnroll.dll的X509Enrollment.CX509CertificateRequestPkcs10方法来生成CSR(Certificate signing request)。

  2)、用户数字证书的自动安装

    要实现用户数字证书在IE浏览器中自动安装,首先要客户端浏览器提交CSR到证书中心服务器,证书中心服务器端根据CSR对用户私钥和公钥进行签名并将签名后的证书返回给客户端。

   在XP、Windows 2003的IE上,通过XEnroll.dll控件的acceptPKCS7方法实现证书自动安装到客户端浏览器,大致步骤如下:


       <object id=”XEnroll” classid=”clsid:127698e4-e730-4e5c-a2b1-21490a70c8a1″ codebase=”xenroll.dll”></object>

        XEnroll.acceptPKCS7

   在Vista,Windows 2008,Windows 7 的IE上,需要使用CertEnroll.dll控件的InstallResponse方法来实现自动安装到客户端浏览器,大致过程如下:

       <object id=”CertEnroll” classid=”clsid:884e2049-217d-11da-b2a4-000e7bbb2b09″ codebase=”CertEnroll.dll”></object>

       var objEnroll = CertEnroll.CreateObject(“X509Enrollment.CX509Enrollment”)

       Call objEnroll.Initialize(1)

       objEnroll.InstallResponse

    此处安装用户数字证书时候并没有自动安装根证书,根证书自动安装的实现方式可以参考:IE中自动安装根数字证书

   3)、服务器端的处理逻辑

      在ejbca中src\java\org\ejbca\ui\web\pub\DemoCertReqServlet.java、src\publicweb\publicweb\templates\certInstTemplate.jsp可以作为例子来理解服务器端对CSR请求处理及服务器响应客户端实现证书自动安装的实现机制。

      以上思路其实应用于openssl的方案也可以。

2、测试页面

<HTML>
<HEAD>
    <meta http-equiv="Content-Type" content="text/html; charset=GBK" />
    <TITLE>VBScript Certificate Enrollment Control Request 例子(使用XEnroll)
    </TITLE>

<OBJECT classid="clsid:127698E4-E730-4E5C-A2b1-21490A70C8A1"
    codebase="xenroll.dll"
    id=XEnroll >
</OBJECT>

<form name="form1" id="form1" action="http://192.168.1.16/ejbca/democertreq" method="post" onsubmit="cert()">  

<center>Certificate Enrollment Control Request 例子<br/><br/>
这里只演示使用XEnroll.dll(XP、Windows 2003的IE)来生成CSR的例子<br/>
在Vista,Windows 2008,Windows 7 的IE上需要使用CertEnroll.dll,与此类似<br/>

    <!--ejbca 中设定的Certificate Profile-->
  <input name="certificateprofile" value="liang" type="hidden">
    <!--ejbca 中设定的End Entity Profile-->
  <input name="entityprofile" value="liang" type="hidden"><br>
  <!-- XEnroll.createPKCS10产生的CSR值 -->
  <input name="pkcs10req" id="pkcs10req"  type="hidden"><br>
  <br>
  <!-- DemoCertReqServlet需要user参数 -->
  <input name="user" value="C=CN,O=yeeach.com,OU=yeeach.com,CN=liang"  type="hidden">
  <table>
      <tr>
          <td align="right">用户DN之Canonical Name(CN):</td><td><input name="canonical_name" value="liang"  type="text"></td>
      </tr>
        <tr>
          <td align="right">用户DN之Organization(O):</td><td><input name="organization" value="yeeach.com"  type="text"></td>
      </tr>
        <tr>
          <td align="right">用户DN之Organization Unit(C):</td><td><input name="organization_unit" value="R&D"  type="text"></td>
      </tr>
        <tr>
          <td align="right">用户DN之County(C):</td><td><input name="country" value="CN"  type="text"></td>
      </tr>
        <tr>
          <td align="right">用户密码:</td><td><input name="password" value="liang" type="password"></td>
      </tr>
        <tr>
          <td align="right">邮箱:</td><td><input name="email" type="text" value="chuanliang@gmail.com"></td>
      </tr>
      <tr><td></td><td></td></tr>
      <tr><td></td><td></td></tr>
      <tr><td align="center" colspan="2"><input value="申请证书" name="submit" type="submit" ></td></tr>
  </table>
  <input name="includeemail" value="true" type="hidden">

 </form>

  <SCRIPT language="VBScript">
  Sub   cert
<!--
' Declare the distinguished name variable.
Dim strDN

' Declare the request variable.
Dim strReq

' Enable error handling.
On Error Resume Next

' Declare consts used by CertRequest object.
const CR_IN_BASE64 = &H1
const CR_IN_PKCS10 = &H100

' Build the DN.

strDN =  "CN="+document.getElementById("canonical_name").value  _
      & ",OU="+document.getElementById("organization_unit").value _
      & ",O="+document.getElementById("organization").value _
      & ",C="+document.getElementById("country").value

' Attempt to use the control, in this case, to create a PKCS #10.
MsgBox("Creating PKCS #10 " & strDN)
document.getElementById("user").value=strDN
strReq = XEnroll.createPKCS10(strDN," ")
' If above line failed, Err.Number will not be 0.
if ( Err.Number <> 0 ) then
    MsgBox("Error in call to createPKCS10 " & Err.Number)
    err.clear
else
    'MsgBox("Submitting request " & strReq)

    ' If the preceding line failed, Err.Number will not be 0.
    if ( Err.Number <> 0 ) then
        MsgBox("Error in Request Submit " & Err.Number)
        err.clear
        return false
    else
        document.getElementById("pkcs10req").value=_
        "-----BEGIN NEW CERTIFICATE REQUEST-----" + _
        CHR(13) + _
        strReq + _
        "-----END NEW CERTIFICATE REQUEST-----"

    end if

end if
  Exit   Sub
  End   Sub
-->
</SCRIPT>
</body>
</html>

 

3、certInstTemplate.jsp

<!-- Header -->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
    <title>EJBCA Certification Authority</title>
    <link rel="stylesheet" href="styles.css" type="text/css" />
    <script type="text/javascript" src="scripts/functions.js"></script>
    <script type="text/vbscript" src="scripts/functions.vbs"></script>
  </head>
  <body>

    <div class="main">
      <div class="content">
<!-- Header -->

<object classid="$CLASSID" id="g_objClassFactory"></object>
<!-- Updated w CertEnroll for Vista
Class ID: {884e2049-217d-11da-b2a4-000e7bbb2b09}
-->
<!-- New updated enrollment activeX-control 2002-09-02 (Q323172)
New Xenroll.dll information:
Class ID: {127698e4-e730-4e5c-a2b1-21490a70c8a1}
sXEnrollVersion="5,131,3659,0"

New Scrdenrl.dll information:
Class ID: {c2bbea20-1f2b-492f-8a06-b1c5ffeace3b}
sScrdEnrlVersion="5,131,3642,0"
-->
<!-- Old Xenroll.dll information:
Class ID: {43F8F289-7A20-11D0-8F06-00C04FC295E1}

Old Scrdenrl.dll information:
Class ID: {80CB7887-20DE-11D2-8D5C-00C04FC29D45}
-->

    <script language="VBScript" type="text/vbscript">
        cert = "MIICdgYJKoZIhvcNAQcCoIICZzCCAmMCAQExADALBgkqhkiG9w0BBwGgggJLMIIC" & _

        ' This function can be moved to functions.vbs when the header is parsed as jsp
        Sub installcertvista
            Dim objEnroll
            Set objEnroll = g_objClassFactory.CreateObject("X509Enrollment.CX509Enrollment")
            Call objEnroll.Initialize(1)    'EnrollmentContext UserContext
            err.clear
            On Error Resume Next
            Call objEnroll.InstallResponse(0, cert, 6, "")    'AllowNone, , XCN_CRYPT_STRING_BASE64_ANY, pw
            If err.number = -2146762487    Then    ' 0x800b0109 Not trusted root
                r = Msgbox("Could not complete the request since, the CAs' certificates were not properly installed.", , "Certificate Management")
            ElseIf err.number <> 0 Then
                r = Msgbox("The certificate could not be installed", , "Certificate Management")
            Else
                r = Msgbox("A new certificate has been installed", , "Certificate Management")
            End If
        End Sub

        Sub installcert
            Err.Clear
            On Error Resume Next
            g_objClassFactory.acceptPKCS7(cert)
            If Err.Number <> 0 Then
                r = Msgbox("The certificate could not be installed in this web browser", , "Certificate Management")
            Else
                r = Msgbox ("A new certificate has been installed", , "Certificate Management")
            End if
        End Sub

        If InStr(navigator.userAgent, "Windows NT 6") <> 0 Then
            installcertvista
        Else
            installcert
        End If
    </script>

    <h1 class="title">Internet Explorer Certificate enrollment.</h1>
    <p>If the installation was completed without any errors, your certificate has
    been installed in your web browser and you may now start using your certificate.<br />
    You can look at your certificate with &quot;<tt>Tools-&gt;Internet
    Options-&gt;Content-&gt;Certificates</tt>&quot;.</p>

<!-- Footer -->
      </div>
    </div>
  </body>
</html>
<!-- Footer -->

 

4、参考资料

   IE中自动安装根数字证书

   Certificate Enrollment API

   Certificate Web Request/Enrollment on Windows Vista/Server 2008

   Simple PKI

   Browser-generated Certificate Requests

 


站内标签:

IE中自动安装根数字证书

基本思路:

1、在XP、Windows 2003的IE上,通过XEnroll.dll控件来完成根数字证书的自动安装。

2、在Vista,Windows 2008,Windows 7 的IE上,需要使用CertEnroll.dll来自动完成根数字证书的自动安装。

3、XEnroll.InstallPKCS7只适用于自动安装根证书。XEnroll.acceptPKCS7 用于安装用户数字证书,但需要配合CSR(Certificate signing request)才能够使用。要实现自动安装用户证书:

在IE中:需要配合Enroll.createPKCS10CSR来生成CSR(Certificate signing request)

在Firefox中:需要配合使用html的keygen标签来生成CSR

4、如果只需要能够下载证书并安装,而不要在IE浏览器中完成证书注销、证书申请等功能,可以采用下载证书文件的方式,MIME Type可以采用

application/x-pkcs12、application/pkcs-12

几个与PKI证书相关的MIME Type:

application/x-x509-ca-cert、application/x-x509-user-cert、application/pkcs10、application/x-pkcs10、application/pkcs-12、

application/x-pkcs12、application/x-pkcs7-signature、application/pkcs7-mime、application/x-pkcs7-mime、

application/pkcs7-mime、application/x-pkcs7-mime、application/x-pkcs7-certreqresp、application/pkcs7-signature

  测试代码:

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%@ page import="java.lang.*,java.io.*" %>
<html>
<head>
<title>IE中自动安装数字证书测试</title>
</head>

<body>
IE中使用XEnroll.InstallPKCS7自动安装根数字证书<br/>
 备注:这里测试的根证书采用Base64编码 X.509格式(CER)<br/>
<%     

StringBuffer server_cert =new StringBuffer();
try {
    String realPath = this.getClass().getClassLoader().getResource("liangchuan.cer").getPath();
    File file = new File(realPath);
    if (!file.exists()) {
        out.println("<HTML><BODY><P>");
        out.println("<h2>根证书文件不存在</h2> <br/>");
        out.println("</P></BODY></HTML>");
        out.flush();
        out.close();
    }else{
        BufferedReader bf=new BufferedReader(new FileReader(file));
        String line=null;
        while((line=bf.readLine())!=null)
            server_cert.append(line);

        bf.close();

    }
}catch(Exception e){
    out.println("<HTML><BODY><P>");
    out.println("<h2>读取证书文件出错</h2> <br/>");
    out.println(e.toString());
    out.println("</P></BODY></HTML>");
    out.flush();
    out.close();
}

String Agent = request.getHeader("User-Agent");
StringTokenizer st = new StringTokenizer(Agent,";");
st.nextToken();
String userBrowser = st.nextToken();
String userOS = st.nextToken();
out.println("你的操作系统为:");
out.println(userOS);
String activexLib="XEnroll";

//检查是否是Windows Vista,Windows 2008,Windows 7,在Vista,Windows 2008,Windows 7上,需要使用 CertEnroll.dll
//Windows 2008 Server, IE7 User-Agent header: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2;...
//Windows Vista, IE7 User-Agent header: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0;...
//Windows 7,IE8 User-Agent header: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1;...

if(userOS.equals("Windows NT 6.0") || userOS.equals("Windows NT 6.1")|| userOS.equals("Windows NT 5.2"))
    activexLib="CertEnroll";

String sPKCS7=server_cert.toString();
%>

<% if(activexLib.equals("XEnroll"))
{ %>
    <object id="XEnroll" classid="clsid:127698e4-e730-4e5c-a2b1-21490a70c8a1" codebase="xenroll.dll"></object>
    <SCRIPT language="VBSCRIPT">
        ON ERROR resume next
        sPKCS7 = "<%= sPKCS7 %>"
        //XEnroll.InstallPKCS7用于安装根证书。
        XEnroll.InstallPKCS7(sPKCS7)

        if err.Number <> 0 then
            if err.number = -2146885628 then
                MsgBox "Keyset does not exist"
            else
                MsgBox "证书下载时出错,错误号="&err.description
            end if
        else
            MsgBox "证书已成功装入"
        end if
</script>
<% } else {%>

//方法来源:
//http://blogs.msdn.com/alejacma/archive/2009/01/28/how-to-create-a-certificate-request-with-certenroll-javascript.aspx
//Vista下由于暂时没有测试环境,方法尚待验证

    <object id="objCertEnrollClassFactory" classid="clsid:884e2049-217d-11da-b2a4-000e7bbb2b09"></object>
    <script language="javascript">
    function InstallCert()
    {
        document.write("<br>Installing certificate...");
        try {
            // Variables
            var objEnroll = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509Enrollment")
            var sPKCS7 = "<%= sPKCS7 %>"
            objEnroll.Initialize(1); // ContextUser
            objEnroll.InstallResponse(0, sPKCS7, 6, ""); // AllowNone = 0, XCN_CRYPT_STRING_BASE64_ANY = 6
        }
        catch (ex) {
            document.write("<br>" + ex.description);
            return false;
        }

    return true;
    }

    InstallCert(); 

    </script>

<% } %>
<%
/*
out.println("用下载方式下载p12格式的文件下载后安装"); 
ClassLoader cl = this.getClass().getClassLoader();
try {
    InputStream is = cl.getResourceAsStream("liangchuan.p12");
    //response.setContentType("application/x-x509-ca-cert");
    response.setContentType("application/x-pkcs12");
    response.addHeader("Content-Disposition", "attachment; filename=liangchuan.p12");
    OutputStream os = response.getOutputStream();
    //InputStream is = new FileInputStream(fileName);
    while (is.available() > 0) {
        char c = (char) is.read();
        os.write(c);
    }
    os.flush();
    is.close(); 
} catch (Exception e) { 

    out.println("<HTML><BODY><P>");
    out.println("<h2>下载证书文件出错</h2> <br/>");
    out.println(e.toString());
    out.println("</P></BODY></HTML>");
    out.flush();
    out.close(); 

}
*/
%>
</body>
</html>

参考资料:

How to create a certificate request with CertEnroll (JavaScript)

Certificate-Related Changes for Windows Vista

How to use Certificate Services Web enrollment pages together with Windows Vista or Windows Server 2008


站内标签:

下一页 »