• 将 Shiro 作为一个许可为基础的应用程序 五:password加密/解密Spring应用


    考虑系统password的安全,眼下大多数系统都不会把password以明文的形式存放到数据库中。

    一把会採取下面几种方式对password进行处理

    password的存储

    “编码”存储

    Shiro 提供了 base64 16 进制字符串编码/解码的 API支持,方便一些编码解码操作。 Shiro内部的一些数据的存储/表示都使用了 base64 16 进制字符串。

    以下两端代码分别对其进行演示

    Stringstr = "hello"; 
    
    Stringbase64Encoded = Base64.encodeToString(str.getBytes()); 
    
    Stringstr2 = Base64.decodeToString(base64Encoded); 
    
    Assert.assertEquals(str,str2); 
    

    通过如上方式能够进行 base64编码/解码操作

    Stringstr = "hello"; 
    
    Stringbase64Encoded = Hex.encodeToString(str.getBytes()); 
    
    Stringstr2 =newString(Hex.decode(base64Encoded.getBytes())); 
    
    Assert.assertEquals(str,str2);

    通过如上方式能够进行 16 进制字符串编码/解码操作

    Hash存储

    散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储password之类的数据,常见的散列算法如 MD5SHA等。一般进行散列时最好提供一个 salt(盐),比方加密password“admin”,产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,能够到一些 md5解密站点非常easy的通过散列值得到password“admin”,即假设直接对password进行散列相对来说破解更easy,此时我们能够加一些仅仅有系统知道的干扰数据,如username和 ID(即盐);这样散列的对象是“password+username+ID”,这样生成的散列值相对来说更难破解。

     

    Stringstr = "hello"; 
    
    Stringsalt = "123"; 
    
    Stringmd5 =new Md5Hash(str, salt).toString();//还能够转换为  toBase64()/toHex()


    如上代码通过盐“123MD5散列“hello”。另外散列时还能够指定散列次数,如 2次表示:md5(md5(str)):“new Md5Hash(str, salt, 2).toString()

    Stringstr = "hello"; 
    
    Stringsalt = "123"; 
    
    Stringsha1 =new Sha256Hash(str, salt).toString();

    使用 SHA256 算法生成对应的散列数据,另外还有如 SHA1SHA512算法。

     

    Shiro 还提供了通用的散列支持:

    Stringstr = "hello"; 
    
    Stringsalt = "123"; 
    
    //内部使用MessageDigest 
    
    StringsimpleHash =new SimpleHash("SHA-1", str, salt).toString();
    


    通过调用 SimpleHash 时指定散列算法,其内部使用了 Java MessageDigest 实现。为了方便使用,Shiro提供了 HashService,默认提供了 DefaultHashService实现

    DefaultHashServicehashService =new DefaultHashService(); //默认算法 SHA-512 
    
    hashService.setHashAlgorithmName("SHA-512");
    
    hashService.setPrivateSalt(newSimpleByteSource("123"));//私盐,默认无
    
    hashService.setGeneratePublicSalt(true);//是否生成公盐,默认false 
    
    hashService.setRandomNumberGenerator(new  SecureRandomNumberGenerator());//用于生成公盐。默认就这个
    
    hashService.setHashIterations(1);//生成 Hash 值的迭代次数
    
    HashRequestrequest =new HashRequest.Builder() 
    
    .setAlgorithmName("MD5").setSource(ByteSource.Util.bytes("hello"))
    
    .setSalt(ByteSource.Util.bytes("123")).setIterations(2).build();
    
    Stringhex =hashService.computeHash(request).toHex();
    

     

    加密存储

    Shiro 还提供对称式加密/解密算法的支持,如 AESBlowfish等;当前还没有提供对非对称加密/解密算法支持,未来版本号可能提供。

    AES 算法实现:

    AesCipherServiceaesCipherService =new AesCipherService(); 
    
    aesCipherService.setKeySize(128);//设置 key 长度
    
    //生成 key 
    
    Keykey=aesCipherService.generateNewKey(); 
    
    Stringtext = "hello"; 
    
    //加密
    
    StringencrptText =
    
    aesCipherService.encrypt(text.getBytes(),key.getEncoded()).toHex(); 
    
    //解密
    
    Stringtext2 = 
    
    newString(aesCipherService.decrypt(Hex.decode(encrptText),key.getEncoded()).getBytes()); 
    
    Assert.assertEquals(text, text2);
    


    password的验证

    使用“password的存储”章节中当中一种存储方式存储password之后,接下来就是登陆时password的验证.

    该过程主要涉及到两个问题:

    (1)    让Shiro知道数据库中存储的password是通过什么方式存储的?

    能够在指定比較器时进行设置

    (2)    让Shiro知道怎样比对数据库与登录时的password?

     

    Shiro主要通过CredentialsMatcher的子类来实现password的对照,Shiro已经实现了比較常见的Matcher,比如Md5CredentialsMatcherSha256CredentialsMatcher等等,假设Shiro提供的Matcher不能满足需求,还能够自己定义Matcher.

    Spring集成Shiropassword验证实例

    本小节以Spring集成Shiro为基础,介绍怎样使用MD5对password进行加密,加入password加密功能须要经过下面三步

    保存password

    作为password的数据源头,首先要确保在password保存时就使用MD5加密

    SpringController相应的方法中,使用下面方法保存password

     

    @RequestMapping("/setting/user/add")
      public String addUser(@Valid User user, BindingResult result, Map<String, Object> model,
          @RequestParam(value = "action") String action) {
        String cryptedPwd = new Md5Hash(user.getPwd()).toString();
        user.setPwd(cryptedPwd);
        userService.saveUser(user);
        return "redirect:/setting/user/" + user.getName();
      }
    

    配置Matcher

    当数据库中存的是MD5形式的password后,就要告诉shiro怎样对登陆时输入的password进行对照,在这里採用默认的HashedCredentialsMatcher作为比較器

     Shiro-config.xml配置例如以下

     

    <!—在自己定义的Realm中配置Matcher,并指定加密算法-->
    
             <beanid="customerRealm" class="com. test.security.CustomerRealm">
    
                       <propertyname="credentialsMatcher">
    
                                <beanclass="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
    
                                         <propertyname="hashAlgorithmName" value="MD5" />
    
                                </bean>
    
                       </property>
    
             </bean>
    


    password校验

    对于CustomerRealm而言,不须要关心password是怎样被匹配的,仅仅须要将用户输入的password传入AuthenticationInfo对象中就可以

     

    @Override
    
      protectedAuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
    
         throws AuthenticationException {
    
       // 获取基于username和password的令牌,authcToken是从LoginController里面//currentUser.login(token)传过来的
    
       UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
    
       User user = userService.findUserByName(token.getUsername());
    
        if(null != user) {
    
         AuthenticationInfo authcInfo =
    
             new SimpleAuthenticationInfo(user.getName(), user.getPwd(),user.getName());
    
         this.setSession(GCloudConstant.CURRENT_USER,user.getName());
    
         return authcInfo;
    
        }else {
    
         return null;
    
        }
    
      }
    


  • 相关阅读:
    oracle 10g 免安装客户端在windows下配置
    sql2005 sa密码
    使用windows live writer 有感
    windows xp SNMP安装包提取
    汉化groove2007
    迁移SQL server 2005 Reporting Services到SQL server 2008 Reporting Services全程截图操作指南
    foxmail 6在使用中的问题
    AGPM客户端连接不上服务器解决一例
    SpringSource Tool Suite add CloudFoundry service
    Java 之 SWing
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4555457.html
Copyright © 2020-2023  润新知