Shiro

$Shiro前端

Apache-shiro 是一種簡便的java安全框架,對於身份認證,受權 。權限管理有着很簡單的使用方法java

三個核心組件:Subject, SecurityManager 和 Realms.
 
 

subject :訪問當前系統的用戶   主體能夠是用戶也能夠是程序  。算法

Shrio SecurityManager :安全管理器 ,shiro 的核心。相似於SpringMVC的前端控制器(DispatcherServlet),接收來自 「subject」 的委託,與認證器 ,受權器等進行交互數據庫

Realm:至關於dataSource 安全的數據源   充當了shiro 與 數據源 的 「鏈接器」 當執行認證,受權時,shiro會從realm中比對信息是否合法合理。apache

Shiro認證(使用ini方式進行測試)---> 全部項目均使用maven方式編寫 安全

shiro.ini(建立一個配置文件存放信息 。模擬從數據庫中獲取信息)框架

 

[users]
#帳號=密碼
chen=123
root=10001

 

新建一個測試類maven

加載配置文件 獲取當前用戶信息性能

經過單獨測試編寫兩個異常信息 ,反饋當用戶名出錯 或者密碼出錯的狀況,測試

package com.shiro.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

/**
 * 測試shiro
 * 
 * @author 18609
 *
 */
public class ShiroTest {

    

    @Test
    public void logintest() {

        // 建立工廠,加載資源 shiro工廠 調用Factory接口
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
        // 經過工廠對象建立SecurityManager對象
        SecurityManager manager = factory.getInstance();
        // 將SecurityManager綁定當前環境中。讓系統隨時訪問SecurityManager對象
        SecurityUtils.setSecurityManager(manager);
        // 建立當前登錄主體 未認證
        Subject subject = SecurityUtils.getSubject();
        // 收集當前用戶信息
        UsernamePasswordToken token = new UsernamePasswordToken("root", "10001");
        try {
            subject.login(token);
            System.out.println("登陸成功");
        } catch (IncorrectCredentialsException e) { // 密碼異常錯誤
            System.out.println("登錄失敗,密碼錯誤!");
        } catch (UnknownAccountException e) { // 帳號異常錯誤
            System.out.println("登錄失敗,帳號不存在!");
        } finally {
            subject.logout();
            System.out.println("註銷成功");
        }
    }
}

經過token 獲取到username  並傳給Realm驗證 ,若是存在相同數據,封裝成以下AuthenticationInfo對象進行返回  不然爲null

自定義一個Realm類 繼承 AuthenticatingRealm 並複寫其類的getName() 實現兩個方法  進行認證操做

package com.shiro.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.AuthenticatingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class MyRealm extends AuthenticatingRealm {

    // 重寫 注意返回值
    public String getName() {
        return "MyRealm";
    }

    // 受權
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            return null;
        }
        
    // 認證
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        System.out.println(token);
        // 獲取用戶名
        String username = (String) token.getPrincipal();
        // 經過用戶名查詢 並返回
        if (!"root".equals(username)) {
            return null;
        }
        String password = "10001";
        // 對比當前信息
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
        return info;

    }

}

shiro-realm.ini

#自定義realm
MyRealm=com.shiro.Realm.MyRealm
#指定自定義realm的實現
securityManager.realms=$MyRealm

 執行流程       

認證成功

 

 Shiro加密認證(使用ini方式進行測試)---> 全部項目均使用maven方式編寫 

shiro 對md5加密有着較好的支持,這裏不說明爲何要進行加密措施。

測試幾種加密方法  越往下 加密措施越好。越不易破解(如下加密方式全選用第三種  密碼  + salt  + 散列次數

package com.shiro.test;

import org.apache.shiro.crypto.hash.Md5Hash;
import org.junit.Test;

public class Md5Test {

    @Test
    public void test() {
        String password = "10001";
        // 密碼加密
        Md5Hash hash = new Md5Hash(password);
        System.out.println("password: " + hash);
        // 密碼 + salt(用戶名)
        Md5Hash hash1 = new Md5Hash(password, "root");
        System.out.println("passsword + salt :" + hash1);
        // 密碼 + salt(用戶名) + 散列次數   安全性能更好
        Md5Hash hash2 = new Md5Hash(password, "root", 3);
        System.out.println("passsword + salt + count :" + hash2);
    }

}

測試類

package com.shiro.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

/**
 * 測試shiro
 * 
 * @author 18609
 *
 */
public class ShiroTest {

    @Test
    public void loginByPasswordtest() {

        // 建立工廠,加載資源 shiro工廠 調用Factory接口
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-md5.ini");
        // 經過工廠對象建立SecurityManager對象
        SecurityManager manager = factory.getInstance();
        // 將SecurityManager綁定當前環境中。讓系統隨時訪問SecurityManager對象
        SecurityUtils.setSecurityManager(manager);
        // 建立當前登錄主體 未認證
        Subject subject = SecurityUtils.getSubject();
        // 收集當前用戶信息
        UsernamePasswordToken token = new UsernamePasswordToken("root", "10001");
        try {
            subject.login(token);
            System.out.println("登陸成功");
        } catch (IncorrectCredentialsException e) { // 密碼異常錯誤
            System.out.println("登錄失敗,密碼錯誤!");
        } catch (UnknownAccountException e) { // 帳號異常錯誤
            System.out.println("登錄失敗,帳號不存在!");
        } finally {
            subject.logout();
            System.out.println("註銷成功");
        }
    }
}

新建passwordRealm類 進行加密認證

package com.shiro.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;

public class PasswordRealm extends AuthorizingRealm {

    //注意返回值
public String getName() { return "PasswordRealm"; } // 受權 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } // 認證 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println(token); // 獲取用戶名 String username = (String) token.getPrincipal(); // 經過用戶名查詢 並返回 if (!"root".equals(username)) { return null; } // passsword + salt + count :2634402341f810a1007d7c4b4521aef5 String password = "2634402341f810a1007d7c4b4521aef5"; // 對比當前信息 1.用戶名 2.密碼 3.salt(加鹽加密ByteSource.Util.bytes("root")) 4.重寫當前的realm名字 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo (username, password, ByteSource.Util.bytes("root"),getName()); return info; } }

 ByteSource.Util.bytes("root")  :進行鹽(salt)加密認證   內填用戶名

不寫此參數使用salt加密 會報錯。報密碼錯誤的問題 由於沒有進行用戶名認證。

shiro-md5.ini

填寫與測試中相關的信息  紅色標註不能更改必填項  藍色標註更改項。

#定義憑證匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次數
credentialsMatcher.hashIterations=3
#指定passwordRealm的realm
myRealm=com.shiro.Realm.PasswordRealm
#引用憑證
myRealm.credentialsMatcher=$credentialsMatcher
#引用指定realm
securityManager.realms=$myRealm

 

經過設置加密的密碼 存入數據庫中 ,並進行加密認證 數據相同時,經過認證。登陸成功。

相關文章
相關標籤/搜索