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

springboot集成shiro權(quán)限管理簡單實(shí)現(xiàn)

 更新時(shí)間:2022年08月05日 10:15:49   作者:夢想實(shí)現(xiàn)家_Z  
這篇文章主要介紹了springboot集成shiro權(quán)限管理簡單實(shí)現(xiàn),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

前言

為了解決項(xiàng)目當(dāng)中的權(quán)限管理問題,我們一般會(huì)選擇引入spring security或者shiro框架來幫助我們更好地更快地構(gòu)建權(quán)限管理體系。

依賴

首先第一步,我們需要給當(dāng)前項(xiàng)目引入對應(yīng)的依賴包。與spring boot集成一般首選starter包。

<!-- shiro權(quán)限管理框架 -->
<dependency>
 ? ?<groupId>org.apache.shiro</groupId>
 ? ?<artifactId>shiro-spring-boot-web-starter</artifactId>
 ? ?<version>1.9.1</version>
</dependency>

配置

無論是spring security還是shiro,兩者都是基于servlet的Filter過濾器機(jī)制實(shí)現(xiàn)的權(quán)限管理。所以第一步配置我們就需要把對應(yīng)的Filter給加入進(jìn)來。

Filter過濾器配置

@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean() {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
 ? ?// 設(shè)置securityManager,負(fù)責(zé)權(quán)限驗(yàn)證的核心事務(wù)處理。
    shiroFilterFactoryBean.setSecurityManager(securityManager());
 ? ?// 配置過濾器鏈
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
 ? ?// anon表示該url不需要經(jīng)過權(quán)限驗(yàn)證
    filterChainDefinitionMap.put("/static/**", "anon");
 ? ?// logout表示用戶登出功能的過濾器;調(diào)用指定的url會(huì)讓已經(jīng)登陸的用戶退出
    filterChainDefinitionMap.put("/logout", "logout");
 ? ?// authc過濾器表示對應(yīng)的url都需要權(quán)限驗(yàn)證才能訪問
    filterChainDefinitionMap.put("/**", "authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
 ? ?// 配置用戶登陸的url。調(diào)用該接口需要傳username和password字段。
    shiroFilterFactoryBean.setLoginUrl("/login");
 ? ?// 登陸成功自動(dòng)跳轉(zhuǎn)頁面
    shiroFilterFactoryBean.setSuccessUrl("/index");
    return shiroFilterFactoryBean;
  }

securityManager配置

看上面代碼,我們就可以分析出,需要把這些Filter過濾器創(chuàng)建出來,除了配置一些需要攔截的url之外,我們還要?jiǎng)?chuàng)建一個(gè)非常核心的securityManager,這個(gè)才是權(quán)限驗(yàn)證過程處理的核心。

@Bean
public DefaultWebSecurityManager securityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(userRealm());
    return securityManager;
}

別看securityManager里面我只設(shè)置了Realm,其實(shí)securityManager就像一個(gè)大領(lǐng)導(dǎo),壓根不干活兒,有啥活都派給底下的小弟去干。

我們來看看securityManager底下到底有哪些小弟;

后續(xù)的博客中會(huì)逐一解析這些小弟的作用,今天就先把如何簡單集成shiro講完。

  • SessionManager:管理用戶session;
  • SubjectDao:負(fù)責(zé)Subject保存和刪除;
  • CacheManager:負(fù)責(zé)緩存管理;
  • Realm:負(fù)責(zé)用戶登陸和權(quán)限驗(yàn)證;
  • RememberMeManager:負(fù)責(zé)實(shí)現(xiàn)remember me功能;
  • EventBus:事件總線;
  • SubjectFactory:創(chuàng)建Subject;

Realm配置

下面我們應(yīng)該要給出如何判斷用戶登陸和鑒定用戶權(quán)限了:

@Bean
public UserRealm userRealm() {
    UserRealm userRealm = new UserRealm();
    userRealm.setCredentialsMatcher(credentialsMatcher());
    return userRealm;
}

因?yàn)镽ealm需要查詢用戶的密碼已經(jīng)改用戶對應(yīng)的角色和權(quán)限,所以我們自定義了自己的Realm。

通過繼承AuthorizingRealm:

package com.example.awesomespring.security;
?
import com.example.awesomespring.bo.AccountInfo;
import com.example.awesomespring.service.AccountService;
import org.apache.shiro.authc.*;
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.ByteSource;
?
import javax.annotation.Resource;
?
public class UserRealm extends AuthorizingRealm {
 ?
   ?@Resource
   ?private AccountService accountService;
?
    @Override
   ?protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
 ? ? ? ?// 從authenticationToken中獲取用戶提交的username
     ? ?String accountName = (String) authenticationToken.getPrincipal();
 ? ? ? ?// 通過username查詢到對應(yīng)的用戶信息
     ? ?AccountInfo accountInfo = accountService.findByAccount(accountName);
     ? ?if (accountInfo == null) {
       ? ? ?return null;
     ?  }
 ? ? ? ?// 取出查詢到的用戶密碼
     ? ?String password = accountInfo.getPassword();
 ? ? ? ?// 取出用戶密碼加密需要用到的鹽值
     ? ?String salt = accountInfo.getSalt();
 ? ? ? ?// 把查詢出來的用戶信息、密碼、加密鹽值、Realm名稱包裝進(jìn)SimpleAuthenticationInfo返回
     ? ?return new SimpleAuthenticationInfo(accountInfo, password, ByteSource.Util.bytes(salt), getName());
    }
 ?
 ? ?// 這個(gè)方法是在用戶登陸成功后,調(diào)用需要權(quán)限才能訪問的接口時(shí)才來鑒定權(quán)限
   ?@Override
   ?protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
 ? ? ? ?// 拿到已經(jīng)登陸的用戶信息
     ? ?AccountInfo accountInfo = (AccountInfo) principalCollection.getPrimaryPrincipal();
     ? ?SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
     ? ?// 下面的角色和權(quán)限需要從數(shù)據(jù)庫中查詢
 ? ? ? ?// 設(shè)置角色
     ? ?authorizationInfo.addRole("User");
     ? ?// 設(shè)置權(quán)限
     ? ?authorizationInfo.addStringPermission("User:read");
 ? ? ? ?// 返回角色和權(quán)限
     ? ?return authorizationInfo;
    }
}

到這里,我們可以看出,Realm就是用來幫助用戶登陸,并且在用戶訪問需要權(quán)限的接口時(shí),查詢出用戶的角色和權(quán)限,交給決策器來決定用戶是否登陸成功,鑒權(quán)是否通過。

密碼加密

這是一個(gè)不容易被注意的點(diǎn),使用默認(rèn)的配置時(shí)只會(huì)簡單的比較輸入的密碼和數(shù)據(jù)庫查出來的密碼是否一致,這顯然是不符合要求的,因?yàn)槲覀償?shù)據(jù)庫里面的密碼是已經(jīng)加密好了的。

另一個(gè)就是我們在創(chuàng)建用戶的時(shí)候也是需要使用到同樣的密碼加密手段,所以我們有必要把密碼加密給拎出來處理一下,做一個(gè)自定義的加密。

@Bean
public CredentialsMatcher credentialsMatcher() {
    return new PasswordHashedCredentialsMatcher("MD5");
}
?
package com.example.awesomespring.security;
?
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.util.ByteSource;
?
/**
 * @author zouwei
 * @className PasswordHashedCredentialsMatcher
 * @date: 2022/7/31 下午3:43
 * @description:
 */
public class PasswordHashedCredentialsMatcher extends HashedCredentialsMatcher {
?
   ?public PasswordHashedCredentialsMatcher(String hashAlgorithmName) {
     ? ?super(hashAlgorithmName);
     ? ?setHashIterations(2);
    }
?
   ?public String encryptedPassword(String passwordString, String salt) {
     ? ?return hashProvidedCredentials(passwordString, ByteSource.Util.bytes(salt), getHashIterations()).toHex();
  }
}

其實(shí)我們就是繼承了HashedCredentialsMatcher,在它的基礎(chǔ)上提高了直接針對密碼加密的功能。這樣既能滿足shiro的登陸驗(yàn)證,又能拿出來用到創(chuàng)建用戶的時(shí)候加密使用。

測試

為了驗(yàn)證我們的配置是否成功,我們需要寫幾個(gè)測試接口:

package com.example.awesomespring.controller;
?
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
?
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
?
  @GetMapping("/{id}")
  @RequiresPermissions("User:info")
  String getUserInfo(@PathVariable String id) {
    log.info("獲取用戶信息開始");
    log.info("請求參數(shù) id:{}", id);
    log.info("獲取用戶信息結(jié)束");
    return "getUserInfo";
  }
?
  @GetMapping("/hello")
  String hello() {
    return "hello world!";
  }
?
  @GetMapping("/read")
  @RequiresPermissions("User:read")
  String read() {
    return "read";
  }
}

上面的幾個(gè)接口,我們?nèi)绻苯釉L問的話,在瀏覽器中,會(huì)被重定向到"/login"頁面,因?yàn)槲覀兡壳皼]有這個(gè)頁面,所以一旦重定向這個(gè)url,說明用戶沒有登陸。

其次我們通過調(diào)用post請求"/login",提交username和password成功登陸后,頁面會(huì)重定向到"/index"頁面,目前我們也是沒有這個(gè)頁面的,不過從響應(yīng)體中可以看到響應(yīng)碼是302。

當(dāng)我們在用戶登陸成功后,再訪問"/user/read"是能正常訪問,并返回結(jié)果"read";如果訪問"/user/123456"是不行的,頁面會(huì)直接報(bào)500錯(cuò)誤。

通過上述測試,我們已經(jīng)初步完成了shiro的集成

到此這篇關(guān)于springboot集成shiro權(quán)限管理簡單實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)springboot 集成shiro內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 17 隨機(jī)數(shù)生成器來了一波穩(wěn)穩(wěn)的增強(qiáng)

    Java 17 隨機(jī)數(shù)生成器來了一波穩(wěn)穩(wěn)的增強(qiáng)

    JDK 當(dāng)中的隨機(jī)數(shù)生成器其實(shí)對于普通開發(fā)者來講基本夠用,不過對于一些比較復(fù)雜的場景來講,原有的類結(jié)構(gòu)對擴(kuò)展并不是很友好,除了 Random 類,JDK 當(dāng)中還提供了另外幾個(gè)隨機(jī)數(shù)的成員,下面文章將詳細(xì)介紹,需要的朋友可以參考一下
    2021-09-09
  • Spring Boot事務(wù)配置操作

    Spring Boot事務(wù)配置操作

    這篇文章主要介紹了Spring Boot事務(wù)配置操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • springboot結(jié)合redis實(shí)現(xiàn)搜索欄熱搜功能及文字過濾

    springboot結(jié)合redis實(shí)現(xiàn)搜索欄熱搜功能及文字過濾

    本文主要介紹了springboot結(jié)合redis實(shí)現(xiàn)搜索欄熱搜功能及文字過濾,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • JAVA實(shí)現(xiàn)經(jīng)典掃雷游戲的示例代碼

    JAVA實(shí)現(xiàn)經(jīng)典掃雷游戲的示例代碼

    windows自帶的游戲《掃雷》是陪伴了無數(shù)人的經(jīng)典游戲,本程序參考《掃雷》的規(guī)則進(jìn)行了簡化,用java語言實(shí)現(xiàn),采用了swing技術(shù)進(jìn)行了界面化處理。感興趣的可以學(xué)習(xí)一下
    2022-01-01
  • SpringBoot小程序推送信息的項(xiàng)目實(shí)踐

    SpringBoot小程序推送信息的項(xiàng)目實(shí)踐

    本文主要介紹了SpringBoot小程序推送信息的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 深入講解基于JDK的動(dòng)態(tài)代理機(jī)制

    深入講解基于JDK的動(dòng)態(tài)代理機(jī)制

    眾所周知相比于靜態(tài)代理,動(dòng)態(tài)代理避免了開發(fā)人員編寫各個(gè)繁鎖的靜態(tài)代理類,下面這篇文章主要給大家介紹了關(guān)于基于JDK的動(dòng)態(tài)代理機(jī)制的相關(guān)資料,文中通過圖文以及示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-07-07
  • Spring Boot中的JdbcTemplate是什么及用法小結(jié)

    Spring Boot中的JdbcTemplate是什么及用法小結(jié)

    Spring Boot中的JdbcTemplate是一個(gè)強(qiáng)大的數(shù)據(jù)庫訪問工具,它簡化了數(shù)據(jù)庫操作的過程,在本文中,我們了解了JdbcTemplate的基本概念,并演示了如何在Spring Boot應(yīng)用程序中使用它,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • 詳解Java中的內(nèi)存屏障

    詳解Java中的內(nèi)存屏障

    這篇文章主要介紹了Java中的內(nèi)存屏障的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-05-05
  • 詳解Java的編譯執(zhí)行與解釋執(zhí)行

    詳解Java的編譯執(zhí)行與解釋執(zhí)行

    這篇文章主要介紹了Java的編譯執(zhí)行與解釋執(zhí)行,對編譯和解釋感興趣的同學(xué),可以參考下
    2021-04-04
  • Java中jar包運(yùn)行后顯示:沒有主清單屬性的解決方案

    Java中jar包運(yùn)行后顯示:沒有主清單屬性的解決方案

    這篇文章主要介紹了Java中jar包運(yùn)行后顯示:沒有主清單屬性的解決方案,文中給大家分析了三個(gè)主要原因,并通過代碼示例和圖文講解的非常詳細(xì),需要的朋友可以參考下
    2024-04-04

最新評論

奎屯市| 张北县| 克东县| 任丘市| 惠来县| 甘肃省| 随州市| 望奎县| 犍为县| 绥芬河市| 申扎县| 翼城县| 宁阳县| 溧水县| 淮滨县| 荣成市| 武宣县| 会宁县| 吴旗县| 阿鲁科尔沁旗| 临沭县| 裕民县| 台山市| 洛南县| 循化| 博湖县| 肇庆市| 博乐市| 塔城市| 高平市| 芦山县| 淮安市| 怀柔区| 遵义县| 锦屏县| 英吉沙县| 双柏县| 祥云县| 锦州市| 遂川县| 富宁县|