欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot整合Shiro實現(xiàn)權限控制的代碼實現(xiàn)

 更新時間:2021年07月23日 08:46:32   作者:yuwenS  
Apache Shiro是一個強大且易用的Java安全框架,執(zhí)行身份驗證、授權、密碼和會話管理,今天通過本文給大家介紹SpringBoot整合Shiro實現(xiàn)權限控制的方法,感興趣的朋友一起看看吧

1、SpringBoot整合Shiro

Apache Shiro是一個強大且易用的Java安全框架,執(zhí)行身份驗證、授權、密碼和會話管理。

1.1、shiro簡介

shiro有個核心組件,分別為Subject、SecurityManager和Realms

  • Subject:相當于當前操作的”用戶“,這個用戶不一定是一個具體的人,是一個抽象的概念,表明的是和當前程序進行交互的任何東西,例如爬蟲、腳本、等等。所有的Subject都綁定到SecurityManager上,與 Subject 的所有交互都會委托給 SecurityManager;可以把 Subject 認為是一個門面;SecurityManager 才是實際的執(zhí)行者。
  • SecurityManager:這個是shiro框架的核心,所有與安全相關的操作都會與它進行交互,它管理者所有的Subject。
  • Realms:充當了Shiro與應用安全數(shù)據(jù)間的”橋梁“,當對用戶執(zhí)行認證(登錄)和授權(訪問控制)驗證時,SecurityManager 需要從 Realm 獲取相應的用戶進行比較以確定用戶身份是否合法;也需要從 Realm 得到用戶相應的角色 / 權限進行驗證用戶是否能進行操作。

如果想要更加深入的了解的shrio可以參考:https://www.w3cschool.cn/shiro/co4m1if2.html

1.2、代碼的具體實現(xiàn)

1.2.1、Maven的配置

	<!--shiro-->
		<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.7.1</version>
        </dependency>
         <!--shiro整合thymeleaf-->
         <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
		<!--shiro緩存-->
		 <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.7.1</version>
        </dependency>

shiro默認是與jsp進行使用的,而這里是shiro整合thymeleaf所有要導入shiro整合thymeleaf的jar包

1.2.2、整合需要實現(xiàn)的類

  • 一般來說整合只需要完成兩個類的實現(xiàn)即可
  • 一個是 ShiroConfig 一個是 CustomerRealm
  • 如果需要添加shiro緩存并且不是自帶的緩存而是redis緩存還需要進行另外兩個類的編寫
  • 一個是 RedisCache 一個是 RedisCacheManager

1.2.3、項目結構

1.2.4、ShiroConfig的實現(xiàn)

未加shiro的緩存

package com.yuwen.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.yuwen.shiro.cache.RedisCacheManager;
import com.yuwen.shiro.realm.CustomerRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {

    //讓頁面shiro標簽生效
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }

    //1、創(chuàng)建shiroFilter   負責攔截所有請求
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //給filter設置安全管理
        factoryBean.setSecurityManager(defaultWebSecurityManager);
        //配置系統(tǒng)的受限資源
        //配置系統(tǒng)公共資源 全部都能訪問的設置anon
        Map<String,String> map = new HashMap<>();
        map.put("/main","authc");//請求這個資源需要認證和授權 authc表示需要認證后才能訪問
        map.put("/admin","roles[admin]"); //表示admin角色才能訪問 roles[]表示需要什么角色才能訪問
        map.put("/manage","perms[user:*:*]"); //表示需要user:*:*權限才能訪問 perms[]表示需要什么權限才能訪問
        //訪問需要認證的頁面如果未登錄會跳轉到/login路由進行登陸
        factoryBean.setLoginUrl("/login");
        //訪問未授權頁面會自動跳轉到/unAuth路由
        factoryBean.setUnauthorizedUrl("/unAuth");
        factoryBean.setFilterChainDefinitionMap(map);
        return factoryBean;
    }
    //2、創(chuàng)建安全管理器
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("getRealm") Realm realm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //給安全管理器設置
        securityManager.setRealm(realm);
        return securityManager;
    }
    //3、創(chuàng)建自定義的realm
    @Bean
    public Realm getRealm(){
        CustomerRealm customerRealm = new CustomerRealm();
        //修改憑證校驗匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //設置加密算法為md5
        credentialsMatcher.setHashAlgorithmName("MD5");
        //設置散列次數(shù)
        credentialsMatcher.setHashIterations(1024);
        customerRealm.setCredentialsMatcher(credentialsMatcher);
        return customerRealm;
    }
}

因為一般在數(shù)據(jù)庫中設置明文密碼不安全,所有我這里對密碼進行了md5加密,我的加密方式為:密碼 = 密碼+鹽+散列次數(shù) 而后進行MD5加密 所以這里創(chuàng)建自定義的realm時需要進行設置匹配器這樣登錄時密碼才能匹配成功

1.2.5、CustomerRealm的實現(xiàn)

package com.yuwen.shiro.realm;

import com.yuwen.pojo.User;
import com.yuwen.pojo.vo.ViewPerms;
import com.yuwen.pojo.vo.ViewRole;
import com.yuwen.service.UserService;
import com.yuwen.shiro.salt.MyByteSource;
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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.util.List;

//自定義realm
public class CustomerRealm extends AuthorizingRealm {

    @Resource
    private UserService userService;
	//授權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //獲取身份信息
        String primaryPrincipal = (String)principalCollection.getPrimaryPrincipal();
        //根據(jù)主身份信息獲取角色 和 權限信息
        List<ViewRole> roles = userService.findRolesByUsername(primaryPrincipal);
        if (!CollectionUtils.isEmpty(roles)){
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            roles.forEach(viewRole -> {
                simpleAuthorizationInfo.addRole(viewRole.getName());
                //權限信息
                List<ViewPerms> perms = userService.findPermsByRoleId(viewRole.getName());
                if (!CollectionUtils.isEmpty(perms)){
                    perms.forEach(viewPerms -> {
                        simpleAuthorizationInfo.addStringPermission(viewPerms.getPName());
                    });
                }
            });
            return simpleAuthorizationInfo;
        }
        return null;
    }
    
	//認證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //獲取登入的身份信息
        String principal = (String) authenticationToken.getPrincipal();
        User user = userService.findByUsername(principal);
        if (!ObjectUtils.isEmpty(user)){
            //ByteSource.Util.bytes(user.getSalt()) 通過這個工具將鹽傳入
            //如果身份認證驗證成功,返回一個AuthenticationInfo實現(xiàn);
            return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),new MyByteSource(user.getSalt()),this.getName());
        }
        return null;
    }
}

在登錄時會自動調(diào)用這個身份驗證 在驗證時如果出錯,會報異常,我在controller層接收了異常并處理

controller層中登錄時的異常處理

@PostMapping("/login")
    public String login(String username,String password){
        //獲取主體對象
        Subject subject = SecurityUtils.getSubject();
        try {
        	//自動調(diào)用CustomerRealm 類中的身份驗證方法
            subject.login(new UsernamePasswordToken(username,password));
            return "index";
        }catch (UnknownAccountException e){ //接收異常并處理
            e.printStackTrace();
            model.addAttribute("msg","用戶名有誤,請重新登錄");
        }catch (IncorrectCredentialsException e){//接收異常并處理
            e.printStackTrace();
            model.addAttribute("msg","密碼有誤,請重新登錄");
        }
        return "login";
    }

1.2.6、shiro緩存配置

定義了shiro緩存,用戶登錄后,其用戶信息、擁有的角色 / 權限不必每次去查,這樣可以提高效率

默認緩存的配置

在 ShiroConfig中 的 getRealm() 方法中開啟緩存管理

 @Bean
    public Realm getRealm(){
        CustomerRealm customerRealm = new CustomerRealm();
        //開啟緩存管理
        customerRealm.setCacheManager(new EhCacheManager());
        //開啟全局緩存
        customerRealm.setCachingEnabled(true);
        //開啟認證緩存
        customerRealm.setAuthenticationCachingEnabled(true);
        customerRealm.setAuthenticationCacheName("authenticationCache");
        //開啟權限緩存
        customerRealm.setAuthorizationCachingEnabled(true);
        customerRealm.setAuthorizationCacheName("authorizationCache");
        return customerRealm;
    }

與reids整合的緩存這里就不說明了,放在源碼里自己查看,源碼在下方

1.2.7、主頁index.html的設置

在這里用標簽來判斷某些區(qū)域需要認證或什么角色或者什么權限才能訪問

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
                xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>首頁</title>
    <link rel="shortcut icon" href="#">
</head>
<body>
<h1>index</h1>
<a href="/logout">退出</a>
<div>
    <a href="/main">main</a> | <a href="/manage">manage</a> | <a href="/admin">admin</a>
</div>
<!--獲取認證信息-->
用戶:<span shiro:principal=""></span><hr>
<!--認證處理-->
<span shiro:authenticated=""><hr>
    顯示認證通過內(nèi)容
</span>
<span shiro:notAuthenticated=""><hr>
    沒有認證時 顯示
</span>
<!--授權角色-->
<span shiro:hasRole="admin"><hr>
    admin角色 顯示
</span>
<span shiro:hasPermission="user:*:*"><hr>
    具有用戶模塊的"user:*:*"權限 顯示
</span>
</body>
</html>

1.3、簡單測試

1.3.1、admin角色所有權限測試

1.3.2、無角色有權限測試

1.3.3、無角色無權限測試


1.4 項目源碼

需要源碼的在這:https://gitee.com/residual-temperature/shiro-demo

到此這篇關于SpringBoot整合Shiro實現(xiàn)權限控制的方法的文章就介紹到這了,更多相關SpringBoot整合Shiro權限控制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JavaWeb實現(xiàn)文件上傳與下載實例詳解

    JavaWeb實現(xiàn)文件上傳與下載實例詳解

    在Web應用程序開發(fā)中,文件上傳與下載功能是非常常用的功能,下面通過本文給大家介紹JavaWeb實現(xiàn)文件上傳與下載實例詳解,對javaweb文件上傳下載相關知識感興趣的朋友一起學習吧
    2016-02-02
  • Java中為什么this可以調(diào)用當前實例

    Java中為什么this可以調(diào)用當前實例

    本文主要介紹了為什么可以通過this關鍵字訪問到當前對象呢,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java數(shù)據(jù)結構之線性表

    Java數(shù)據(jù)結構之線性表

    線性表是其組成元素間具有線性關系的一種數(shù)據(jù)結構,對線性表的基本操作主要有,獲取元素,設置元素值,遍歷,插入,刪除,查找,替換,排序等。而線性表可以采用順序儲存結構和鏈式儲存結構,本節(jié)主要講解順序表、單鏈表以及雙鏈表的各種基本操作。
    2017-03-03
  • java向mysql插入數(shù)據(jù)亂碼問題的解決方法

    java向mysql插入數(shù)據(jù)亂碼問題的解決方法

    這篇文章主要為大家詳細介紹了java向mysql插入數(shù)據(jù)亂碼問題的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Spring Boot搭建文件上傳服務的方法

    Spring Boot搭建文件上傳服務的方法

    這篇文章主要為大家詳細介紹了Spring Boot搭建文件上傳服務的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Java中的隨機數(shù)詳解

    Java中的隨機數(shù)詳解

    這篇文章主要介紹了Java中的隨機數(shù),需要的朋友可以參考下
    2014-02-02
  • Java中使用@CrossOrigin和Proxy解決跨域問題詳解

    Java中使用@CrossOrigin和Proxy解決跨域問題詳解

    這篇文章主要介紹了Java中使用@CrossOrigin和Proxy解決跨域問題詳解,在Web開發(fā)中,如果前端頁面和后端接口不在同一個域名下,就會發(fā)生跨域請求的問題,同源策略是瀏覽器的一種安全策略,它限制了來自不同源的客戶端腳本在瀏覽器中運行時的交互,需要的朋友可以參考下
    2023-12-12
  • Java并發(fā)編程之Semaphore詳解

    Java并發(fā)編程之Semaphore詳解

    這篇文章主要介紹了Java并發(fā)編程之Semaphore詳解,Semaphore信號量可以用來控制同時訪問特定資源的線程數(shù)量,常用于限流場景,Semaphore接收一個int整型值,表示 許可證數(shù)量,需要的朋友可以參考下
    2023-11-11
  • MyBatis動態(tài)SQL特性詳解

    MyBatis動態(tài)SQL特性詳解

    動態(tài)SQL可以省略很多拼接SQL的步驟,使用類似于JSTL方式,下面這篇文章主要給大家介紹了關于Mybatis動態(tài)SQL特性的相關資料,文字通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • java使用dbcp2數(shù)據(jù)庫連接池

    java使用dbcp2數(shù)據(jù)庫連接池

    這篇文章主要為大家詳細介紹了java使用dbcp2數(shù)據(jù)庫連接池的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10

最新評論