zoukankan      html  css  js  c++  java
  • 将 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;
    
        }
    
      }
    


  • 相关阅读:
    【算法笔记】多线程斐波那契数列
    RAID技术详解
    Mysql 语句汇总(性能篇)
    JS 网页打印解决方案
    MyEclipse修改
    几个需要学习的点和技术
    MyEclipse配色字体等配置的解决方案
    使用hibernate 分表做增删改查
    Web平台开发流程以及规范
    easyui使用总结
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4555457.html
Copyright © 2011-2022 走看看