BlogJava 联系 聚合 管理  

Blog Stats

随笔档案


bitmap

bitmap

2009年7月8日 #

     摘要: /**   * author:annegu  * date:2009-07-16   */ annegu做了一个简单的Http多线程的下载程序,来讨论一下多线程并发下载以及断点续传的问题。 这个程序的功能,就是可以分多个线程从目标地址上下载数据,每个线程负责下载一部分,并可以支持断点续传和超时重连。 下载的方法是do...  阅读全文
posted @ 2009-07-20 20:27 bitmap| 编辑 收藏

     摘要: ECC ECC-Elliptic Curves Cryptography,椭圆曲线密码编码学,是目前已知的公钥体制中,对每比特所提供加密强度最高的一种体制。在软件注册保护方面起到很大的作用,一般的序列号通常由该算法产生。     当我开始整理《Java加密技术(二)》的时候,我就已经在开始研究ECC了,但是关于Java实现ECC算法的资料实在是太少了,无论是国...  阅读全文
posted @ 2009-07-19 09:08 bitmap| 编辑 收藏

     摘要: DSA DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。如果数据和签名不匹配则认为验证失败!数字签名的作用就是校验数据在传输...  阅读全文
posted @ 2009-07-17 21:27 bitmap| 编辑 收藏

最近与一位创业公司的朋友私下交流了一些项目管理和软件开发的心得,是互联网创业型公司,通过几次的交流,加深了我对互联网创业的一些感悟,本来不太想拿到桌面上说,但实在忍不住,还是想拿出来和希望创业的朋友讨论下。

那么我对互联网公司的比较感兴趣的地方主要体现在软件质量和技术管理方面,以下2点可以作为讨论的提纲:

     1 软件质量,尽管质量是我们嘴边经常挂念的一个词,但不少创业型公司的投机心理太重,在与这些负责人的交流中发现,谈论的更多的是新想法、新概念,有非常重的商业气息,当然这没什么不好,但我看了他们的一些产品后发现,他们所做的产品用户体验非常糟糕,就拿界面来说,非常的粗糙,由于有家公司做的产品和易趣类似,我特意打开2个窗口对比一下,总觉得易趣的看起来比较舒服,他们整体布局倒模仿易趣倒挺像,但问题就体现在细节上,图片失真严重、字体风格不一致、细节处理的不到位。好了,那就凑合着看吧,发现该产品的功能非常的多,但让人郁闷的是,很多功能是有问题的,比如明明提示我系统给偶发了个邮件,但就是找不到,有时候提交表单是可以的,有时候见到一堆java异常错误。所以我觉得这就是典型的追求功能的庞大而导致质量的缩水。

    其实自从豆瓣开始流行后,大家都意识到功能做的简洁原来是有好处的,有不少创业者声称自己要向豆瓣看齐,鄙视csdn,坚决走简洁之路,但让我纳闷的是,很少有人真正的坚持下去,我有个同学06年底曾在一家创业公司玩过python,准备做一个很有趣的网站,叫做抱怨网,其实是蛮有创意的,不久前JE不是有个哥们在四处发帖说我爱我家黑中介的事,其实本来这个网站就是干这个事的,专门揭不良企业底的,但做着做着,成了巨无霸,开始是把大众点评网的功能加进去,接着又开始融进赶集网的分类信息功能,最后有把智联招聘的招聘功能加上了,结局就是1年不到,网站不出意料的死掉了,原因就是用户体验差,根本不感兴趣!最后我替他们老板做了下反思,其实说实话,我还是很理解创业人的心,看到好东西都想要,而且之前几年在互联网圈钱谁都眼红。另外,他们的功能尽管是抄袭别人的,但还是有一定的特色与盈利模式,并且各个功能分的也蛮清的。 所以我觉得失败的原因不能简单的归结为功能太多,而是质量,小公司也就那几号人,作为开发人员,面对这么多的需求,只有拼命的赶进度,丫还有时间考虑质量或者用户体验吗?所以没有一定的资本与一批强有力的管理和开发人员,切勿贪大求全,否则很可能就是在生产垃圾。其实质量这个东西从高的层面上说就是用户体验的好坏,bug少不见得质量高,但用户体验差的东西绝对就是垃圾。

    最近市面上有个说法有个说法是30w足以模仿个淘宝,我认为就是扯淡,误导了很多创业者,认为花点银子,雇几个人,就可以轻松抄袭淘宝了,咱先不说市场投资,只谈技术,表面上看淘宝,丫就是一个破网站,但背后的技术你看的见吗?稳定性、性能、维护、可扩展性,这些都和软件质量息息相关,直接影响着用户的满意度,你确定真的做到了吗?淘宝的架构师一年的薪水也30w了。所以我觉得创业者要领悟毛泽东思想,采用各个击破的战术,在有限的资源下约束的自己产品的功能,做到小而美。

     这里举个正面的例子,有家位于芝加哥、名为37 Signals的小公司,正是这种拥抱限制的方式之代表者。37 Signals最初是一家网页设计资讯公司,后来为了满足自身需求而将业务扩展到软件开发领域。他们编写了一些用于项目管理的内部工具。为了和客户沟通, 就向客户开放了部分系统。公司创始人和总裁杰森•弗瑞德(Jason Fried)解释说,在他们自己意识到之前,已经做出了一套基于网页的应用。又做了4个月,他们把软件转换为称作Basecamp的服务。 Basecamp发布于2004年2月,很快在类似Flickr和Google的Gmail等新Web富应用天堂中名列前茅。

     Basecamp只是这家公司花一年多时间投入少量程序员做出来的一系列值得注意的小而精的产品之一。Basecamp之后是Ta-da List,用于保存和共享待办事项(及类似事项)列表。几个月后推出了Backpack,它允许用户保存和共享便签及文件。每种产品都可靠并易于使用,而 且都是精心设计的。每种产品通常也都只包括少量新特性。例如,Basecamp就有一些精巧的电子邮件功能:和其他服务和程序一样,也可以设置邮件到达提醒——还可以从另外的计算机或手机等移动设备向Backpack网页发送邮件,邮件文本就会在页面上显示出来。

     2 技术管理,你会发现很多公司的负责人不是很懂技术,但却是负责技术的,丫今天听到SOA是个好东西,号令纷纷SOA,反正大家都不理解这个含糊不清的东西,做呗,看谁能忽悠的过谁,一般来讲,创业型公司为了节约成本,不会预留专门的QA,有专门的测试人员就不错了,所以缺乏一个质量保证的环节,遇到问题怎么办?谁做的谁改,改成什么样没人关心,只要负责人看到问题解决了就可以了,但,我想问的是,不良代码背后的隐患你知道吗?结果就是你咬牙给开发人员开工资,开发人员假装帮你实现梦想,或者说造就一批划水的人。其实很多东西不是钱的问题,也不要以为多开点薪水就可以留住人心。另外我觉得很多技术负责人喜欢把东西模糊化,比如把软件即服务的理念挂在嘴边,但做起来是另一码子事,我觉得作为一个技术负责人自己就要身先士卒,至少在创业公司是这样,这样才更有说服力,遇到问题自己应当第一个冲上去,拿出具体的解决方案,对代码应当做到精细管理,做到心中有数。说到底,创业公司得有一个技术核心,一个真正能实现你的想法的人,一个可以让大家凝聚起来的人,不至于让大家划水的人。

好了,先说那么多,希望各位准备创业的同仁能真正的树立精品意识,打造精品,实现梦想

posted @ 2009-07-14 13:14 bitmap| 编辑 收藏

问题的产生原因
       页面提交给Action去进行业务处理,Action再跳转回前台页面,但这时URL依然是“页面提交给Action的链接”,这时前台刷新一下页面,就变成再次执行了一次提交操作。

 

解决思路
     1,在Action页面中跳转的时候用重定向,可以在struts-config.xml中配置<forward ... redirect=“true”>
不过这种方法会使得request中放置数据丢失;
     2,用Token令牌环来实现
          提交到Action的时候,进行一系列操作,然后保存一个标志,这时再跳转到前台页面。如果前台页面刷新的话,Action通过查看是否有标志,就能判断用户是刷新还是提交。

 

Action中操作令牌的方法
      一: saveToken(HttpServletRequest request)
            创建一个新令牌,并将其保存在当前用户的会话中,如果用户的会话不存在,将首先创建新会话对象
      二: isTokenValid(HttpServletRequest request)
            判断存储在当前会话中的令牌值和请求参数中的令牌值是否匹配,如果匹配,返回true,否则返回false 。
            以下情况返回false:
                  1,用户的HttpSession不存在
                  2,用户Session中没有保存令牌值
                  3,在用户请求参数中没有令牌值
                  4,存储在用户Session范围内的令牌值和请求参数中 的令牌值不匹配
       三:resetToken()
             删除保存在Session范围内的令牌值

 

示例代码

1,进入目标页,如 http://www.bt285.cn ,通过IndexAction转发,其中需要保存令牌:

public ActionForward execute(ActionMapping mapping, ActionForm form,   
        HttpServletRequest request, HttpServletResponse response)   
        
throws Exception {   
    saveToken(request);   
    
return mapping.findForward("index");// http://www.5a520.cn   
}
  
 2,目标页面(test.jsp)需要使用Struts标签库:
<body>  
    
<html:form action=" http://www.5a520.cn test.do" method="post">  
        
<input type="submit" value="提交" />  
    
</html:form>  
</body>  
当提交test.jsp时提交到TestAction处理:
<struts-config>  
    
<form-beans>  
        
<form-bean name="testForm" type="com.tanlan.struts.form.TestForm">  
        
</form-bean>  
    
</form-beans>  
    
<action-mappings>  
        
<action path="/index" type="com.tanlan.struts.action.IndexAction">  
            
<forward name="index" path="/index.jsp"></forward>  
        
</action>  
        
<action path="/test" type="com.tanlan.struts.action.TestAction"  
            name
="testForm" input="/index.jsp">  
            
<forward name="test" path="/test.jsp"></forward>  
            
<forward name="error" path="/error.jsp"></forward>  
        
</action>  
    
</action-mappings>  
</struts-config>  

至此,大功告成!

完整示例请参考附件。

 

posted @ 2009-07-12 12:55 bitmap| 编辑 收藏

     摘要: 接下来我们分析DH加密算法,一种适基于密钥一致协议的加密算法。 DH Diffie-Hellman算法(D-H算法),密钥一致协议。是由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。简单的说就是允许两名用户在公开媒体上交换信息以生成"一致"的、可以共享的密钥。换句话说,就是由甲方产出一对密钥(公钥、私钥),乙方依照甲方公钥产生乙方密钥对(公钥、私钥)。以此为基线,作...  阅读全文
posted @ 2009-07-11 20:01 bitmap| 编辑 收藏

     摘要: RSA     这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。     这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥。相当于只有一把钥匙,如果...  阅读全文
posted @ 2009-07-09 21:08 bitmap| 编辑 收藏

除了DES,我们还知道有DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)等多种对称加密方式,其实现方式大同小异,这里介绍对称加密的另一个算法——PBE

PBE
    PBE——Password-based encryption(基于密码加密)。其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法保证数据的安全性。是一种简便的加密方式。



通过java代码实现如下:

 

import java.security.Key;   
import java.util.Random;   
  
import javax.crypto.Cipher;   
import javax.crypto.SecretKey;   
import javax.crypto.SecretKeyFactory;   
import javax.crypto.spec.PBEKeySpec;   
import javax.crypto.spec.PBEParameterSpec;   
  
/**  
 * PBE安全编码组件 
http://www.bt285.cn   http://www.5a520.cn 
 *   
 * 
@author 梁栋  
 * 
@version 1.0  
 * 
@since 1.0  
 
*/
  
public abstract class PBECoder extends Coder {   
    
/**  
     * 支持以下任意一种算法  
     *   
     * <pre>  
     * PBEWithMD5AndDES   
     * PBEWithMD5AndTripleDES   
     * PBEWithSHA1AndDESede  
     * PBEWithSHA1AndRC2_40  
     * </pre>  
     
*/
  
    
public static final String ALGORITHM = "PBEWITHMD5andDES";   
  
    
/**  
     * 盐初始化  
     *   
     * 
@return  
     * 
@throws Exception  
     
*/
  
    
public static byte[] initSalt() throws Exception {   
        
byte[] salt = new byte[8];   
        Random random 
= new Random();   
        random.nextBytes(salt);   
        
return salt;   
    }
   
  
    
/**  
     * 转换密钥<br>  
     *   
     * 
@param password  
     * 
@return  
     * 
@throws Exception  
     
*/
  
    
private static Key toKey(String password) throws Exception {   
        PBEKeySpec keySpec 
= new PBEKeySpec(password.toCharArray());   
        SecretKeyFactory keyFactory 
= SecretKeyFactory.getInstance(ALGORITHM);   
        SecretKey secretKey 
= keyFactory.generateSecret(keySpec);   
  
        
return secretKey;   
    }
   
  
    
/**  
     * 加密  
     *   
     * 
@param data  
     *            数据  
     * 
@param password  
     *            密码  
     * 
@param salt  
     *            盐  
     * 
@return  
     * 
@throws Exception  
     
*/
  
    
public static byte[] encrypt(byte[] data, String password, byte[] salt)   
            
throws Exception {   
  
        Key key 
= toKey(password);   
  
        PBEParameterSpec paramSpec 
= new PBEParameterSpec(salt, 100);   
        Cipher cipher 
= Cipher.getInstance(ALGORITHM);   
        cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);   
  
        
return cipher.doFinal(data);   
  
    }
   
  
    
/**  
     * 解密  
     *   
     * 
@param data  
     *            数据  
     * 
@param password  
     *            密码  
     * 
@param salt  
     *            盐  
     * 
@return  
     * 
@throws Exception  
     
*/
  
    
public static byte[] decrypt(byte[] data, String password, byte[] salt)   
            
throws Exception {   
  
        Key key 
= toKey(password);   
  
        PBEParameterSpec paramSpec 
= new PBEParameterSpec(salt, 100);   
        Cipher cipher 
= Cipher.getInstance(ALGORITHM);   
        cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);   
  
        
return cipher.doFinal(data);   
  
    }
   
}
  

再给出一个测试类:
import static org.junit.Assert.*;   
  
import org.junit.Test;   
  
/**  
 *   
 * 
@author 梁栋  http://www.5a520.cn http://www.feng123.com
 * 
@version 1.0  
 * 
@since 1.0  
 
*/
  
public class PBECoderTest {   
  
    @Test  
    
public void test() throws Exception {   
        String inputStr 
= "abc";   
        System.err.println(
"原文: " + inputStr);   
        
byte[] input = inputStr.getBytes();   
  
        String pwd 
= "efg";   
        System.err.println(
"密码: " + pwd);   
  
        
byte[] salt = PBECoder.initSalt();   
  
        
byte[] data = PBECoder.encrypt(input, pwd, salt);   
  
        System.err.println(
"加密后: " + PBECoder.encryptBASE64(data));   
  
        
byte[] output = PBECoder.decrypt(data, pwd, salt);   
        String outputStr 
= new String(output);   
  
        System.err.println(
"解密后: " + outputStr);   
        assertEquals(inputStr, outputStr);   
    }
   
  
}
  

控制台输出:

  • 原文: abc   
  • 密码: efg   
  • 加密后: iCZ0uRtaAhE=   
  •   
  • 解密后: abc  

  •  

     

    posted @ 2009-07-08 22:22 bitmap| 编辑 收藏