shiro自定義realm支持MD5算法認證(六)

1.1     散列算法

通常需要對密碼 進行散列,常用的有md5、sha,

 

對md5密碼,如果知道散列後的值可以通過窮舉算法,得到md5密碼對應的明文。

建議對md5進行散列時加salt(鹽),進行加密相當 於對原始密碼+鹽進行散列。(鹽就相當於加入一個隨機數)

正常使用時散列方法:

在程序中對原始密碼+鹽進行散列,將散列值存儲到數據庫中,並且還要將鹽也要存儲在數據庫中。

 

如果進行密碼對比時,使用相同 方法,將原始密碼+鹽進行散列,進行比對。

 

1.2 MD5測試

package cn.qlq.authentication;


import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;

/**
 * 測試MD5算法
* @author: qlq
* @date :  2017年7月28日下午9:31:45
 */
public class MD5Test {
    
    public static void main(String[] args) {
        
        //原始 密碼 
        String source = "111111";
        //鹽
        String salt = "qwerty";
        //散列次數
        int hashIterations = 2;
        //上邊散列1次:f3694f162729b7d0254c6e40260bf15c
        //上邊散列2次:36f2dfa24d0a9fa97276abbe13e596fc
        
        
        //構造方法中:
        //第一個參數:明文,原始密碼 
        //第二個參數:鹽,通過使用隨機數
        //第三個參數:散列的次數,比如散列兩次,相當 於md5(md5(''))
        Md5Hash md5Hash = new Md5Hash(source, salt, hashIterations);
        String password_md5 =  md5Hash.toString();
        System.out.println(password_md5);
        
        
//        第二種方法
        //第一個參數:散列算法 
        SimpleHash simpleHash = new SimpleHash("md5", source, salt, hashIterations);
        System.out.println(simpleHash.toString());
        
        
        
    }

}

 

 

-------------------------------------   自定義realm支持散列算法--------------------------------------------------------------------------------------

 新建realm(CustomRealmMd5)   如果未採用md5算法則不用紅色部分第三個參數:

 

package cn.qlq.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

/**
 * 自定義realm實現MD5散列算法加密
* @author: qlq
* @date :  2017年7月28日下午9:33:14
 */
public class CustomRealmMd5 extends AuthorizingRealm {

    // 設置realm的名稱
    @Override
    public void setName(String name) {
        super.setName("customRealmMd5");
    }

    // 用於認證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {

        // token是用戶輸入的
        // 第一步從token中取出身份信息
        String userCode = (String) token.getPrincipal();

        // 第二步:根據用戶輸入的userCode從數據庫查詢
        // ....

        // 如果查詢不到返回null
        // 數據庫中用戶賬號是zhangsansan
        /*
         * if(!userCode.equals("zhangsansan")){// return null; }
         */

        // 模擬從數據庫查詢到密碼,散列值
        String password = "f3694f162729b7d0254c6e40260bf15c";
        //String password = new String((char[]) token.getCredentials()); //用戶輸入密碼     
        // 從數據庫獲取salt
        String salt = "qwerty";
        //上邊散列值和鹽對應的明文:111111

        // 如果查詢到返回認證信息AuthenticationInfo
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                userCode, password, ByteSource.Util.bytes(salt), this.getName());

        return simpleAuthenticationInfo;
    }

    // 用於授權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        // TODO Auto-generated method stub
        return null;
    }

}

 

  在realm中配置憑證匹配器

 

 

 

測試:

 

// 自定義realm實現散列值匹配
        @Test
        public void testCustomRealmMd5() {

            // 創建securityManager工廠,通過ini配置文件創建securityManager工廠
            Factory<SecurityManager> factory = new IniSecurityManagerFactory(
                    "classpath:shiro-realm-md5.ini");

            // 創建SecurityManager
            SecurityManager securityManager = factory.getInstance();

            // 將securityManager設置當前的運行環境中
            SecurityUtils.setSecurityManager(securityManager);

            // 從SecurityUtils裏邊創建一個subject
            Subject subject = SecurityUtils.getSubject();

            // 在認證提交前準備token(令牌)
            // 這裏的賬號和密碼 將來是由用戶輸入進去
            UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
                    "111111");

            try {
                // 執行認證提交
                subject.login(token);
            } catch (AuthenticationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            // 是否認證通過
            boolean isAuthenticated = subject.isAuthenticated();

            System.out.println("是否認證通過:" + isAuthenticated);

        }
      

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章