最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文總結(jié) Shiro 實戰(zhàn)教程

 更新時間:2023年04月10日 11:38:08   作者:Java Fans  
shiro是apache的一個開源框架,是一個權(quán)限管理的框架,實現(xiàn) 用戶認證、用戶授權(quán),這篇文章詳細總結(jié)了shiro用法,感興趣的同學可以參考閱讀

1.權(quán)限的管理

1.1 什么是權(quán)限管理

基本上涉及到用戶參與的系統(tǒng)都要進行權(quán)限管理,權(quán)限管理屬于系統(tǒng)安全的范疇,權(quán)限管理實現(xiàn)對用戶訪問系統(tǒng)的控制,按照安全規(guī)則或者安全策略控制用戶可以訪問而且只能訪問自己被授權(quán)的資源。

權(quán)限管理包括用戶身份認證和授權(quán)兩部分,簡稱認證授權(quán)。對于需要訪問控制的資源用戶首先經(jīng)過身份認證,認證通過后用戶具有該資源的訪問權(quán)限方可訪問。

1.2 什么是身份認證

身份認證,就是判斷一個用戶是否為合法用戶的處理過程。最常用的簡單身份認證方式是系統(tǒng)通過核對用戶輸入的用戶名和口令,看其是否與系統(tǒng)中存儲的該用戶的用戶名和口令一致,來判斷用戶身份是否正確。對于采用指紋等系統(tǒng),則出示指紋;對于硬件Key等刷卡系統(tǒng),則需要刷卡。

1.3 什么是授權(quán)

授權(quán),即訪問控制,控制誰能訪問哪些資源。主體進行身份認證后需要分配權(quán)限方可訪問系統(tǒng)的資源,對于某些資源沒有權(quán)限是無法訪問的

2.什么是shiro

Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.

Shiro 是一個功能強大且易于使用的Java安全框架,它執(zhí)行身份驗證、授權(quán)、加密和會話管理。使用Shiro易于理解的API,您可以快速輕松地保護任何應用程序—從最小的移動應用程序到最大的web和企業(yè)應用程序。

 Shiro是apache旗下一個開源框架,它將軟件系統(tǒng)的安全認證相關(guān)的功能抽取出來,實現(xiàn)用戶身份認證,權(quán)限授權(quán)、加密、會話管理等功能,組成了一個通用的安全認證框架。

3.shiro的核心架構(gòu)

3.1 Subject

Subject即主體,外部應用與subject進行交互,subject記錄了當前操作用戶,將用戶的概念理解為當前操作的主體,可能是一個通過瀏覽器請求的用戶,也可能是一個運行的程序。 Subject在shiro中是一個接口,接口中定義了很多認證授權(quán)相關(guān)的方法,外部程序通過subject進行認證授權(quán),而subject是通過SecurityManager安全管理器進行認證授權(quán)

3.2 SecurityManager

SecurityManager即安全管理器,對全部的subject進行安全管理,它是shiro的核心,負責對所有的subject進行安全管理。通過SecurityManager可以完成subject的認證、授權(quán)等,實質(zhì)上SecurityManager是通過Authenticator進行認證,通過Authorizer進行授權(quán),通過SessionManager進行會話管理等。

SecurityManager是一個接口,繼承了Authenticator, Authorizer, SessionManager這三個接口。

3.3 Authenticator

Authenticator即認證器,對用戶身份進行認證,Authenticator是一個接口,shiro提供ModularRealmAuthenticator實現(xiàn)類,通過ModularRealmAuthenticator基本上可以滿足大多數(shù)需求,也可以自定義認證器。

3.4 Authorizer

Authorizer即授權(quán)器,用戶通過認證器認證通過,在訪問功能時需要通過授權(quán)器判斷用戶是否有此功能的操作權(quán)限。

3.5 Realm

Realm即領(lǐng)域,相當于datasource數(shù)據(jù)源,securityManager進行安全認證需要通過Realm獲取用戶權(quán)限數(shù)據(jù),比如:如果用戶身份數(shù)據(jù)在數(shù)據(jù)庫那么realm就需要從數(shù)據(jù)庫獲取用戶身份信息。

  • ? 注意:不要把realm理解成只是從數(shù)據(jù)源取數(shù)據(jù),在realm中還有認證授權(quán)校驗的相關(guān)的代碼。

3.6 SessionManager

sessionManager即會話管理,shiro框架定義了一套會話管理,它不依賴web容器的session,所以shiro可以使用在非web應用上,也可以將分布式應用的會話集中在一點管理,此特性可使它實現(xiàn)單點登錄。

3.7 SessionDAO

SessionDAO即會話dao,是對session會話操作的一套接口,比如要將session存儲到數(shù)據(jù)庫,可以通過jdbc將會話存儲到數(shù)據(jù)庫。

3.8 CacheManager

CacheManager即緩存管理,將用戶權(quán)限數(shù)據(jù)存儲在緩存,這樣可以提高性能。

3.9 Cryptography

? Cryptography即密碼管理,shiro提供了一套加密/解密的組件,方便開發(fā)。比如提供常用的散列、加/解密等功能。

4. shiro中的認證

4.1 認證

身份認證,就是判斷一個用戶是否為合法用戶的處理過程。最常用的簡單身份認證方式是系統(tǒng)通過核對用戶輸入的用戶名和口令,看其是否與系統(tǒng)中存儲的該用戶的用戶名和口令一致,來判斷用戶身份是否正確。

4.2 shiro中認證的關(guān)鍵對象

  • Subject:主體

訪問系統(tǒng)的用戶,主體可以是用戶、程序等,進行認證的都稱為主體;

  • Principal:身份信息

是主體(subject)進行身份認證的標識,標識必須具有唯一性,如用戶名、手機號、郵箱地址等,一個主體可以有多個身份,但是必須有一個主身份(Primary Principal)。

  • credential:憑證信息

是只有主體自己知道的安全信息,如密碼、證書等。

4.3 認證流程

4.4 認證的開發(fā)

1. 創(chuàng)建項目并引入依賴

<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-core</artifactId>
  <version>1.5.3</version>
</dependency>

2. 引入shiro配置文件并加入如下配置

[users]
mosin=1234
tom=1234

3.開發(fā)認證代碼

/**
 * @author: mosin
 * @version: v1.0
 */
public class ShiroTest {

    public static void main(String[] args) {
        //創(chuàng)建默認的安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //創(chuàng)建安全管理器需要的realm對象
        IniRealm iniRealm = new IniRealm("classpath:realm.ini");
        //安全管理器設(shè)置realm對象
        defaultSecurityManager.setRealm(iniRealm);
        //將安全管理器注入安全工具類   用于獲取認證的主體
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //獲取認證的主體
        Subject subject = SecurityUtils.getSubject();
        //創(chuàng)建令牌
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("mosin", "1234");

        try {
            //認證 通過沒有任何的異常
            subject.login(usernamePasswordToken);
            //驗證是否通過
            boolean authenticated = subject.isAuthenticated();
            System.out.println("認證通過:"+authenticated);
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用戶名錯誤!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密碼錯誤!");
        }

    }

}
  • DisabledAccountException(帳號被禁用)
  • LockedAccountException(帳號被鎖定)
  • ExcessiveAttemptsException(登錄失敗次數(shù)過多)
  • ExpiredCredentialsException(憑證過期)等

4.5 自定義Realm

上邊的程序使用的是Shiro自帶的IniRealm,IniRealm從ini配置文件中讀取用戶的信息,大部分情況下需要從系統(tǒng)的數(shù)據(jù)庫中讀取用戶信息,所以需要自定義realm。

1.shiro提供的Realm

2.根據(jù)認證源碼認證使用的是SimpleAccountRealm

SimpleAccountRealm的部分源碼中有兩個方法一個是 認證 一個是 授權(quán),

public class SimpleAccountRealm extends AuthorizingRealm {
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        SimpleAccount account = getUser(upToken.getUsername());

        if (account != null) {

            if (account.isLocked()) {
                throw new LockedAccountException("Account [" + account + "] is locked.");
            }
            if (account.isCredentialsExpired()) {
                String msg = "The credentials for account [" + account + "] are expired";
                throw new ExpiredCredentialsException(msg);
            }

        }

        return account;
    }

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = getUsername(principals);
        USERS_LOCK.readLock().lock();
        try {
            return this.users.get(username);
        } finally {
            USERS_LOCK.readLock().unlock();
        }
    }
}

3.自定義realm

/**
 * 自定義realm
 */
public class CustomerRealm extends AuthorizingRealm {
    //認證方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    //授權(quán)方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String principal = (String) token.getPrincipal();
        if("mosin".equals(principal)){
            return new SimpleAuthenticationInfo(principal,"123",this.getName());
        }
        return null;
    }
}

4.使用自定義Realm認證

public class TestAuthenticatorCustomerRealm {
    public static void main(String[] args) {
        //創(chuàng)建securityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //IniRealm realm = new IniRealm("classpath:realm.ini");
        //設(shè)置為自定義realm獲取認證數(shù)據(jù)
        defaultSecurityManager.setRealm(new CustomerRealm());
        //將安裝工具類中設(shè)置默認安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //獲取主體對象
        Subject subject = SecurityUtils.getSubject();
        //創(chuàng)建token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("mosin", "1234");
        try {
            subject.login(token);//用戶登錄
            System.out.println("登錄成功");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用戶名錯誤!!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密碼錯誤!!!");
        }

    }
}

4.6 使用MD5和Salt

實際應用是將鹽和散列后的值存在數(shù)據(jù)庫中,自動realm從數(shù)據(jù)庫取出鹽和加密后的值由shiro完成密碼校驗。

1.自定義md5+salt的realm

/**
 * 自定義md5+salt realm
 */
public class CustomerMD5Realm extends AuthorizingRealm {

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

        String principal = (String) token.getPrincipal();
        //根據(jù)用戶名查詢數(shù)據(jù)庫
        if("mosin".equals(principal)){
            // 參數(shù)1:用戶名  參數(shù)2:密碼 參數(shù)3:鹽 參數(shù)4:自定義realm的名字
            System.out.println(this.getName());
            return new SimpleAuthenticationInfo(principal, "800d63a19662b2ba95bc2ffa01ab4804", ByteSource.Util.bytes("mosin"),this.getName());
        }
        return null;
    }
}

2.使用md5 + salt 認證

public class CustomerMD5RealmTest {

    public static void main(String[] args) {

        //創(chuàng)建安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //創(chuàng)建自定義MD5Realm對象
        CustomerMD5Realm customerMD5Realm = new CustomerMD5Realm();
        //創(chuàng)建密碼認證匹配器對象
        HashedCredentialsMatcher md5 = new HashedCredentialsMatcher("MD5");
        //設(shè)置散列的次數(shù)
        md5.setHashIterations(1024);
        //設(shè)置密碼認證匹配器對象
        customerMD5Realm.setCredentialsMatcher(md5);
        //設(shè)置安全管理器的 認證安全數(shù)據(jù)源
        defaultSecurityManager.setRealm(customerMD5Realm);
        //設(shè)置安全工具類的安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //獲取認證的主體
        Subject subject = SecurityUtils.getSubject();
        //創(chuàng)建令牌
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("mosi", "12345");

        //登錄認證
        try {
            subject.login(usernamePasswordToken);
            System.out.println("認證通過:"+subject.isAuthenticated());
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用戶名錯誤");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密碼錯誤!!!");
        }

    }
}

5. shiro中的授權(quán)

5.1 授權(quán)

授權(quán),即訪問控制,控制誰能訪問哪些資源。主體進行身份認證后需要分配權(quán)限方可訪問系統(tǒng)的資源,對于某些資源沒有權(quán)限是無法訪問的。

5.2 關(guān)鍵對象

授權(quán)可簡單理解為who對what(which)進行How操作:

Who,即主體(Subject),主體需要訪問系統(tǒng)中的資源。

What,即資源(Resource),如系統(tǒng)菜單、頁面、按鈕、類方法、系統(tǒng)商品信息等。資源包括資源類型和資源實例,比如商品信息為資源類型,類型為t01的商品為資源實例,編號為001的商品信息也屬于資源實例。

How,權(quán)限/許可(Permission),規(guī)定了主體對資源的操作許可,權(quán)限離開資源沒有意義,如用戶查詢權(quán)限、用戶添加權(quán)限、某個類方法的調(diào)用權(quán)限、編號為001用戶的修改權(quán)限等,通過權(quán)限可知主體對哪些資源都有哪些操作許可。

5.3 授權(quán)流程

5.4 授權(quán)方式

  • 基于角色的訪問控制
    • RBAC基于角色的訪問控制(Role-Based Access Control)是以角色為中心進行訪問控制
  • 基于資源的訪問控制
    • RBAC基于資源的訪問控制(Resource-Based Access Control)是以資源為中心進行訪問控制
if(subject.isPermission("user:update:01")){ //資源實例
  //對01用戶進行修改
}
if(subject.isPermission("user:update:*")){  //資源類型
  //對01用戶進行修改
}

5.5 權(quán)限字符串

? 權(quán)限字符串的規(guī)則是:資源標識符:操作:資源實例標識符,意思是對哪個資源的哪個實例具有什么操作,“:”是資源/操作/實例的分割符,權(quán)限字符串也可以使用*通配符。

例子:

  • 用戶創(chuàng)建權(quán)限:user:create,或user:create:*
  • 用戶修改實例001的權(quán)限:user:update:001
  • 用戶實例001的所有權(quán)限:user:*:001

5.6 shiro中授權(quán)編程實現(xiàn)方式

  • 編程式
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
	//有權(quán)限
} else {
	//無權(quán)限
}
  • 注解式
@RequiresRoles("admin")
public void hello() {
	//有權(quán)限
}
  •  標簽式
JSP/GSP 標簽:在JSP/GSP 頁面通過相應的標簽完成:
<shiro:hasRole name="admin">
	<!— 有權(quán)限—>
</shiro:hasRole>
注意: Thymeleaf 中使用shiro需要額外集成!

5.7 開發(fā)授權(quán)

1.realm的實現(xiàn)

public class CustomerRealm extends AuthorizingRealm {
    //授權(quán)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String primaryPrincipal = (String) principals.getPrimaryPrincipal();
        System.out.println("primaryPrincipal = " + primaryPrincipal);

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRole("admin");

        simpleAuthorizationInfo.addStringPermission("user:update:*");
        simpleAuthorizationInfo.addStringPermission("product:*:*");


        return simpleAuthorizationInfo;
    }

    //認證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String principal = (String) token.getPrincipal();
        if("xiaochen".equals(principal)){
            String password = "3c88b338102c1a343bcb88cd3878758e";
            String salt = "Q4F%";
            return new SimpleAuthenticationInfo(principal,password, 
                                                ByteSource.Util.bytes(salt),this.getName());
        }
        return null;
    }

}

2.授權(quán)

public class CustomerMD5RealmTest {

    public static void main(String[] args) {

        //創(chuàng)建安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //創(chuàng)建自定義MD5Realm對象
        CustomerMD5Realm customerMD5Realm = new CustomerMD5Realm();
        //創(chuàng)建密碼認證匹配器對象
        HashedCredentialsMatcher md5 = new HashedCredentialsMatcher("md5");
        //設(shè)置加密的次數(shù)
        md5.setHashIterations(1024);
        //設(shè)置密碼認證匹配器對象
        customerMD5Realm.setCredentialsMatcher(md5);
        //設(shè)置安全管理器的 認證安全數(shù)據(jù)源
        defaultSecurityManager.setRealm(customerMD5Realm);
        //設(shè)置安全工具類的安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);

        //獲取認證的主體
        Subject subject = SecurityUtils.getSubject();
        //創(chuàng)建令牌
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("mosin", "12345");

        //登錄認證
        try {
            subject.login(usernamePasswordToken);
            System.out.println("認證通過:"+subject.isAuthenticated());
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用戶名錯誤");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密碼錯誤!!!");
        }

        //基于角色的控制
        //單角色控制
        System.out.println("========hasRole==========");
        boolean admin = subject.hasRole("admin");
        System.out.println("hash admin role:"+admin);

        //多角色控制
        System.out.println("========hasAllRoles==========");
        List<String> roles = Arrays.asList("admin", "user");
        boolean booleans = subject.hasAllRoles(roles);
        System.out.println("booleans = " + booleans);

        // 基于任意角色的控制
        System.out.println("========hasRoles==========");
        boolean[] booleans1 = subject.hasRoles(roles);
        for (boolean b : booleans1) {
            System.out.println("b = " + b);
        }

        //基于權(quán)限字符串的權(quán)限控制
        System.out.println("========isPermitted==========");
        boolean permitted = subject.isPermitted("user:update:*");
        System.out.println("permitted = " + permitted);

        //分別具有哪些權(quán)限
        boolean[] permitted1 = subject.isPermitted("user:update:*", "product:update:*");
        for (boolean b : permitted1) {
            System.out.println("b = " + b);
        }
        //同時具有哪些權(quán)限
        boolean permittedAll = subject.isPermittedAll("user:update:*", "product:update:*");
        System.out.println("permittedAll = " + permittedAll);

    }
}

以上就是一文總結(jié) Shiro 實戰(zhàn)教程的詳細內(nèi)容,更多關(guān)于Java Shiro實戰(zhàn)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • elasticsearch head的安裝及使用過程解析

    elasticsearch head的安裝及使用過程解析

    這篇文章主要介紹了elasticsearch head的安裝及使用過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-09-09
  • Java反射機制詳解

    Java反射機制詳解

    Java的反射機制是在運行狀態(tài)中,對于任何一個類,都可以知道這個類的所有屬性和方法,對于任何一個對象,都可以調(diào)用它所有的方法和屬性,修改部分類型信息。本文就來詳細講講Java反射機制的使用
    2022-07-07
  • 詳解JVM中的本機內(nèi)存跟蹤

    詳解JVM中的本機內(nèi)存跟蹤

    在本文里小編給大家整理了一篇關(guān)于JVM中的本機內(nèi)存跟蹤的相關(guān)知識點內(nèi)容,有興趣的朋友們參考學習下。
    2019-07-07
  • Java httpClient介紹以及使用示例

    Java httpClient介紹以及使用示例

    這篇文章主要介紹了Java httpClient介紹以及使用示例,幫助大家更好的利用Java實現(xiàn)HTTP請求,感興趣的朋友可以了解下
    2020-10-10
  • 基于Java的Socket編寫的C/S聊天程序?qū)崿F(xiàn)

    基于Java的Socket編寫的C/S聊天程序?qū)崿F(xiàn)

    這篇文章主要介紹了基于Java的Socket編寫的C/S聊天程序?qū)崿F(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • SpringBoot整合阿里云開通短信服務詳解

    SpringBoot整合阿里云開通短信服務詳解

    這篇文章主要介紹了如何利用SpringBoot整合阿里云實現(xiàn)短信服務的開通,文中的示例代碼講解詳細,對我們學習有一定幫助,需要的可以參考一下
    2022-03-03
  • IDEA插件(BindED)之查看class文件的十六進制

    IDEA插件(BindED)之查看class文件的十六進制

    這篇文章主要介紹了IDEA插件(BindED)之查看class文件的十六進制,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 解決spring boot 配置文件后綴的一個坑

    解決spring boot 配置文件后綴的一個坑

    這篇文章主要介紹了spring boot 配置文件后綴的一個坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Spring Security如何使用URL地址進行權(quán)限控制

    Spring Security如何使用URL地址進行權(quán)限控制

    這篇文章主要介紹了Spring Security如何使用URL地址進行權(quán)限控制,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • RocketMq深入分析講解兩種削峰方式

    RocketMq深入分析講解兩種削峰方式

    當上游調(diào)用下游服務速率高于下游服務接口QPS時,那么如果不對調(diào)用速率進行控制,那么會發(fā)生很多失敗請求,通過消息隊列的削峰方法有兩種,這篇文章主要介紹了RocketMq深入分析講解兩種削峰方式
    2023-01-01

最新評論

长葛市| 望奎县| 万年县| 西畴县| 化州市| 宜良县| 德庆县| 泗阳县| 新民市| 大方县| 康乐县| 鱼台县| 哈巴河县| 郧西县| 大石桥市| 康马县| 镇江市| 恩平市| 福泉市| 巴里| 虎林市| 江孜县| 石景山区| 嘉禾县| 安顺市| 自治县| 渭源县| 翁源县| 宁陵县| 武穴市| 金平| 陈巴尔虎旗| 郓城县| 哈巴河县| 临潭县| 永福县| 万全县| 新宾| 且末县| 彭山县| 台山市|