posts - 122,  comments - 25,  trackbacks - 0
1、介绍
通过证书验证用户身份(浏览器),其核心是利用cookie实现http和https的信息共享(同域名)。如http://test.abc.com/app/index.html 发现未验证后,跳转到https://test.abc.com:443/app/checkCrt.html身份验证,要求出去证书,确认后将身份信息带入http请求头部,跳转到原请求页面(http://test.abc.com/app/index.html ),读取身份信息后进入页面(出于安全考虑Cookie需要加密)。

流程图

流程说明:
登录流程详细介绍:
1). 未登录用户访问页面 如:http://test.abc.com/app/index.html
2). 【CertAuthValve】判断是否访问受限制资源,如访问受限制的资源则判断用户身份是否已验证,未验证则将用户重定向到身份验证页面,原始请求的url做为
query的一部分,登录成功后可以跳转回来, 如:https://test.abc.com:443/app/checkCrt.htm?done=/index.html。
3). 【CertAuthValve】对于https请求,apache读取请求提供的用户证书,获取证书中的邮件地址,并将该信息写入请求头中。
4). 【GetUserInfoValve】读取请求头,获取刚刚设置的用户邮件地址信息,进一步获取用户的详细信息,然后将这些信息加密后放入cookie中。
5). 登录完成,将用户外部重定向回原始页面。
2、具体实现
1)、安装apache、ssh、java、jboss等环境,略。
2)、生成服务证书和服务密码
openssl req -new -x509 -nodes -out /home/admin/app/conf/ssl.crt/server.crt -keyout /home/admin/app/conf/ssl.crt/server.key -days 3600
因为要和内网证书交互,所以需要一个内网证书公钥文件,可以通过以下方式获取:
获取方法:IE->工具->Internet选项->内容->证书->受信任的根证书颁发机构,找到intranet行,点击导出,选择下一步,选择Base64编码X.509,将证书文件保存为intranet-ca.crt,拷贝到目录/home/admin/app/conf/ssl.crt/。
3)、apache(httpd.conf)配置
应用和身份验证页面放在一起,所以需要同时配置两个虚拟主机,同时监听80(处理http请求)、443(处理https请求)端口。
#监听端口
Listen 80
Listen 443

#app的虚拟主机配置
NameVirtualHost *:80
<VirtualHost *:80>
    ServerAdmin sa@abc.com
    ServerName test.abc.com
    DocumentRoot /home/admin/app/target/app/htdocs/
</VirtualHost>

#身份验证的虚拟主机配置
NameVirtualHost *:443
<VirtualHost *:443>
    ServerAdmin sa@abc.com
    ServerName test.abc.com
    DocumentRoot /home/admin/app/target/app/htdocs/
    SSLEngine on
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+SSLv3:+EXP:+eNULL

    #该指令为虚拟主机指定证书文件名。
    SSLCertificateFile /home/admin/app/conf/ssl.crt/server.crt

    #该指令为证书指定一个对应的私钥文件
    SSLCertificateKeyFile /home/admin/app/conf/ssl.crt/server.key

    #该指令为指定一个包含Certificate Authority证书的文件
    #证书公钥
    SSLCACertificateFile /home/admin/app/conf/ssl.crt/intranet-ca.cer
    SSLProxyEngine on
    RewriteEngine on
    #设置客户端证书验证为必须
    SSLVerifyClient require

    #因为一个CA证书能够被另一个CA证书验证,所以可以形成一个CA证书链.使用该指令可指定服务器验证用户证书时可以查找多少个CA证明。
    #设置认证深度:一般用默认10。
    SSLVerifyDepth  10

    #把mod_ssl里的变量变为全局环境的变量
    SSLOptions +StdEnvVars

    #将证书中的邮件地址添加到请求头中
    RequestHeader unset SSL_CLIENT_S_DN_Email
    RequestHeader add SSL_CLIENT_S_DN_Email %{SSL_CLIENT_S_DN_Email}e
</VirtualHost>

4)、代码片段
        //CertAuthValve.java
        
//判断session中是否有用户邮箱地址
        SessionValue session = SessionHelper.getSessionValue(rundata);
        if (StringUtil.isNotEmpty(session.getCropEmail())) {
            return null;
        }
        
        // 从内网证书中获取用户邮箱地址: SSL_CLIENT_S_DN_Email
        String cropEmail = rundata.getRequest().getHeader(SSL_CLIENT_HEADER_MAIL);
        if (StringUtil.isNotEmpty(cropEmail)) {
            //将邮箱地址保存到session
            session.setCropEmail(cropEmail);
            SessionHelper.saveSessionValue(rundata, session);
            if (log.isDebugEnabled()) {
                log.debug("用户" + session.getCropEmail() + "已经通过证书验证");
            }
            return null;
        }
        
        URIBrokerService uriBrokerService = (URIBrokerService) getWebxComponent().getService(
                URIBrokerService.SERVICE_NAME);
        URIBroker noPermissionUriBroker = uriBrokerService.getURIBroker(CHECK_CRT_URL);
        //请求的原始URL & 验证的URL
        String requestPath = rundata.getPathInfo().replace("_", "");
        String checkCrtUrl = (String) noPermissionUriBroker.getPath().get(
                noPermissionUriBroker.getPath().size() - 1);

        try {
            //原始请求判断
            if (requestPath.equalsIgnoreCase(checkCrtUrl)) {
                //当前是https请求,但是依然不能得到证书信息,转到禁止页面
                
//(要将禁止页面加入到允许访问的配置文件中,不然会导致循环重定向)
                URIBroker uriBroker = uriBrokerService.getURIBroker("forbidden");
                rundata.setRedirectLocation(uriBroker.render());
            } else {
                //转到证书验证页面
                rundata.setRedirectLocation(noPermissionUriBroker.render() + "?done=" + rundata.getPathInfo());
            }
        } catch (IOException e) {
            log.error("权限验证重定向出错", e);
        }
        return new BreakPipeline();

        //GetUserInfoValve.java
        Object user = rundata.getSession().getAttribute("userInfo");
        if (user == null) {
            SessionValue session = SessionHelper.getSessionValue(rundata);
            String email = session.getCropEmail();
            Employe employe = PersonInfoUtil.getPersonInfoByEmail(email);

            // 写入cookie
            session.setEmployeeId(employe.getEmployeId());
            session.setName(employe.getName());
            session.setCropEmail(employe.getEmail());
            SessionHelper.saveSessionValue(rundata, session);
        }

posted @ 2011-12-09 16:09 josson 阅读(2407) | 评论 (0)编辑 收藏
受限于证书的原因,以前经常不得已用IE打开一些应用。其实有一工具可以帮助我们导出IE证书,用于firefox,解决证书的困惑。

Jailbreak [https://www.isecpartners.com/application-security-tools/jailbreak.html],win32的一个小软件,可以帮助我们导出IE证书,使用很简单。
1、windows环境(xp\win7均可),以adminstrator登录;
2、下载jailbreak,解包后,运行jailbreak.exe(非jailbreak.msc);
3、导出证书:Certificates - Current User > 个人 > 证书,选所有任务导出;


选择导出私钥。
4、在firefox中导入证书:选项 > 高级 > 查看证书(您的证书) > 导入(刚导出证书文件);

5、搞定。
posted @ 2011-12-09 13:54 josson 阅读(3035) | 评论 (1)编辑 收藏

互联网的产品大都是面向海量用户的服务,且用户分布区域广泛,其教育水平、习惯也大多不同,具有高度不确定性,我们必须非常关注用户的行为和反馈。因而,在互联网产品服务的整个用户研究,需求分析、产品研发及交付服务的过程中,都采用探索式、适应性的研发理念进行产品的研发。通常,会把整个产品研发周期划分为若干个迭代,采用迭代式的演进过程,不断的去交付新的产品特性,并通过观察用户的行为和反馈获取,进而随时调整产品的思路和方向。一切以用户价值为核心是互联网产品最核心的特点,而以价值驱动的敏捷开发方法非常符合这一特点。

一、敏捷项目管理实践


从阿里软件开始,内贸团队就一直在实行着敏捷项目管理实践,通过小步快跑,快速迭代、增量交付用户价值,不断获取用户反馈,持续、快速的调整产品,验证并适合用户价值。正是通过这些实践活动,我们以迭代的、增量的交付用户价值,最大限度的保证产品朝着符合用户实际需求方向发展。目前,在内贸团队应用较成熟的敏捷实践活动有:

1)、迭代计划(Sprint Planning Meeting)

2)、每日晨会(Daily Scrum Meeting) & 任务墙(Task Wall)

3)、功能预演(Spring Review)

4)、项目总结(Retrospect Meeting)

5)、结对编程(Pair Programming)

6)、其他技术实践活动等

 二、敏捷团队

1)、自组织文化

如google、facebook等互联网企业,他们很少甚至没有特定的项目流程,通常怎么敏捷怎么做,具有浓厚的工程师驱动文化。我们则有较完整的开发流程指导和规范我们的项目研发工作,相比而言,丧失了一些灵活性和积极性,不利于我们工程师自我管理、自我驱动意识的培养。臃肿、缺乏灵活性的流程同互联网产品快速更新、快速发展是不相适应的,同时也弱化我们的责任心意识。除了遵守详尽的流程,我们是否可以换个角度、换种方法,提倡和营造一种自我管理、自我驱动的开发文化,省却一些并不能给我们带来帮助却影响效率的流程呢?

敏捷团队的自组织特性弱化了团队技术领导这个角色,强调自我管理和自我驱动。虽然这对工程师的素质要求更高,相对技术能力更难提高。但是,团队导向很重要,我们努力营造这样的氛围,从小团队做起,逐渐锻炼和培养自组织团队。相信在这样的开发氛围下,会让我们做的更高效、更敏捷,可以走的更稳、更远。

2)、追求一体化

一体化团队作为敏捷开发方法中最具精益思想基因的实践,是指每个项目团队包括分析,开发,测试等角色,使团队满足一个需求从设计,开发到测试各个阶段顺利完成,达到符合质量标准并满足需求的软件。这种以项目/产品为单位的虚拟团队,坐在一起,全身心的为共同的目标而努力,可以更好的凝聚项目组中的各种角色,消除部门墙。 

 3)、追求全功能

这里所指的全功能是希望项目团队能打破工程师角色之间的边界,如研发、测试和前端工程师的界线,消除开发、测试流程中一些潜在浪费,提高效率。在项目团队内部通过角色互换,不限角色的结对工作,加强不同角色,不同模块间的知识传递,打破技术壁垒,帮助员工从不同视角理解项目,锻炼技能,进而增加团队均衡生产的能力。

为什么要提倡打破边界?项目整体效率依赖于项目过程中各环节的工作效率,而整体效率的优化往往依赖于均衡生产(精益思想的按需生产),即消除生产的波峰(过度生产)和波谷(生产不足),只有局部效率的增加无法直接转换为整体效率的增加(就象桶能装多少水,决定于最短的那块板)。整体效率的优化要求IT团队消除技能壁垒,培养多面手,根据计划的的变动,弹性地调整任务,达到各角色和流程之间的平衡。

三、质量保证

我们追求开发效率,同时也注重项目质量。如何去保证质量?就象美国的一位教授爱德化.戴明(W.Edwards Deming)所说:“我们应该停止依靠大量检验来保证质量,而是要改进工艺流程,从一开始就生产出优质的产品”。我们要在整个开发过程中多个环节去保证质量。同时,质量保证是整个团队的责任,就如同前面所说的追求全功能团队,打破边界。

至于在哪些环节采用哪些实践,我们先做个分类,按是否能被系统用户感知将质量问题区分内部质量和外部质量。外部质量指能直接被系统用户感知,如运行缓慢,不可操作或是操作复杂就属于外部质量低劣。而不能直接为系统用户所直接感知的要素,对产品键壮性、可维护性有深远影响的问题就属于外部质量,如系统设计的一致性、代码可读性、逻辑完整性等。内部质量对用户的影响比较间接,但比外部质量意义更深远。一般来说,系统内部质量优秀,外部质量仍有可能很差。而内部质量差的系统,外部质量肯定也不怎么样。

1)、外部质量保证

在外部质量保证上,大部分会在开发后期介入,可以通过性能测试、自动化测试及工程师的功能测试来保证,通过这些实践活动发现并保证例如运行缓慢、不可操作等质量问题不会存在。针对交互特别复杂的web应用,可以更多的考虑采用webui自动化测试工具,如selenium、pwaitr(b2b)、automan(淘宝)等,可以很好的完成那些简单、重复的TC用例,可以大大提高测试效率,解决测试工程师的资源瓶颈。

2)、内部质量保证

相对于外部质量,内部质量问题影响更为深远,在开发开始阶段就应该去保证。如通过单元测试、静态代码扫描(PMD\findbugs)、持续集成、重构、结对编程、code review等多种实践活动来保证项目代码的健康。

除了一些实践活动去检查代码质量外,更为重要的是研发工程师对内部质量的重视,如果工程师没有形成良好的质量意识,很可能这些实践也只是停留于形式,并不能带来较好的结果。如我们在开发过程中的编码规范、单元测试的质量及覆盖率,code review的及时性及问题是否持续跟进等等。此外,有选择的采用结对编程实践,有助于质量的提高。

本文以敏捷、精益(消除浪费、按需生产)思想的角度试图去探讨一种适合互联网公司的产品开发体系,上述概要的介绍了项目管理、团队、质量方面的一些敏捷实践活动,主要涉及了我们对敏捷方面的经验分享或者是些正在研究探讨的课题。文中涉及的实践活动,后续我将逐一展开详细介绍,帮助大家更好的理解和认识。希望本文的分享能成为一个引子,引起大家对敏捷开发的思考和讨论,或者更好的了解敏捷和精益思想。
posted @ 2011-06-13 15:53 josson 阅读(488) | 评论 (0)编辑 收藏
<2011年6月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

常用链接

留言簿(3)

随笔分类

随笔档案

收藏夹

搜索

  •  

最新评论

阅读排行榜

评论排行榜