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

spring-shiro權(quán)限控制realm實(shí)戰(zhàn)教程

 更新時(shí)間:2021年10月15日 12:02:20   作者:Moshow鄭鍇  
這篇文章主要介紹了spring-shiro權(quán)限控制realm實(shí)戰(zhàn)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

spring-shiro權(quán)限控制realm

用戶與角色實(shí)體

Role.java

@Data
@Entity
public class Role {
    @Id
    @GeneratedValue
    private Integer id;
    private Long userId;
    private String role;
}

User.java

@Data
@Entity
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String username;
    private String password;
}

Realm類

首先建立 Realm 類,繼承自 AuthorizingRealm,自定義我們自己的授權(quán)和認(rèn)證的方法。Realm 是可以訪問(wèn)特定于應(yīng)用程序的安全性數(shù)據(jù)(如用戶,角色和權(quán)限)的組件。

Realm.java

public class Realm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    //授權(quán)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //從憑證中獲得用戶名
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        //根據(jù)用戶名查詢用戶對(duì)象
        User user = userService.getUserByUserName(username);
        //查詢用戶擁有的角色
        List<Role> list = roleService.findByUserId(user.getId());
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        for (Role role : list) {
            //賦予用戶角色
            info.addStringPermission(role.getRole());
        }
        return info;
    }
    //認(rèn)證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //獲得當(dāng)前用戶的用戶名
        String username = (String) authenticationToken.getPrincipal();
        //從數(shù)據(jù)庫(kù)中根據(jù)用戶名查找用戶
        User user = userService.getUserByUserName(username);
        if (userService.getUserByUserName(username) == null) {
            throw new UnknownAccountException(
                    "沒(méi)有在本系統(tǒng)中找到對(duì)應(yīng)的用戶信息。");
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(),getName());
        return info;
    }
}

Shiro 配置類

ShiroConfig.java

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        //以下是過(guò)濾鏈,按順序過(guò)濾,所以/**需要放最后
        //開(kāi)放的靜態(tài)資源
        filterChainDefinitionMap.put("/favicon.ico", "anon");//網(wǎng)站圖標(biāo)
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(myRealm());
        return defaultWebSecurityManager;
    }
    @Bean
    public MyRealm myRealm() {
        MyRealm myRealm = new MyRealm();
        return myRealm;
    }
}

控制器

UserController.java

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/")
    public String index() {
        return "index";
    }
    @GetMapping("/login")
    public String toLogin() {
        return "login";
    }
    @GetMapping("/admin")
    public String admin() {
        return "admin";
    }
    @PostMapping("/login")
    public String doLogin(String username, String password) {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "redirect:admin";
    }
    @GetMapping("/home")
    public String home() {
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.checkPermission("admin");
        } catch (UnauthorizedException exception) {
            System.out.println("沒(méi)有足夠的權(quán)限");
        }
        return "home";
    }
    @GetMapping("/logout")
    public String logout() {
        return "index";
    }
}

Service

UserService.java

@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    public User getUserByUserName(String username) {
        return userDao.findByUsername(username);
    }
    @RequiresRoles("admin")
    public void send() {
        System.out.println("我現(xiàn)在擁有角色admin,可以執(zhí)行本條語(yǔ)句");
    }
}

shiro權(quán)限不生效原因分析

shiro遇到的坑

-項(xiàng)目中使用shiro做登錄校驗(yàn)和權(quán)限管理,在配置權(quán)限時(shí)遇到小坑,記錄一下。

  • 環(huán)境:springboot+freemarker+shiro
  • 場(chǎng)景:后臺(tái)管理,配置菜單以及按鈕權(quán)限,分為三個(gè)層級(jí),一二級(jí)暫時(shí)只考慮是否查看權(quán)限,第三層級(jí)為頁(yè)面按鈕權(quán)限,分增刪改查。詳情看圖
  • 問(wèn)題:一二層級(jí)正常,第三層級(jí)權(quán)限不起作用!

權(quán)限標(biāo)簽定義如下:

標(biāo)簽定義 頁(yè)面一 頁(yè)面二
第一層級(jí) one:view two:view
第二層級(jí) one:page1:view two:page2:view
第三層級(jí) one:page1:view:add two:page2:view:add

開(kāi)始懷疑是數(shù)據(jù)庫(kù)沒(méi)有錄入,查看后權(quán)限標(biāo)簽與角色已對(duì)應(yīng),排除。

后面懷疑是頁(yè)面問(wèn)題,后面把第三層級(jí)標(biāo)簽與第一二層級(jí)同一頁(yè)面,依然不起作用,排除。

后面懷疑是權(quán)限標(biāo)簽定義問(wèn)題,把第三層級(jí)標(biāo)簽改為one:page1:data:add,奇跡出現(xiàn),權(quán)限生效。證實(shí)權(quán)限標(biāo)簽定義出了問(wèn)題。

問(wèn)題原因:權(quán)限標(biāo)簽定義問(wèn)題

但是后來(lái)想想為什么會(huì)出現(xiàn)這種問(wèn)題,每個(gè)標(biāo)簽都是獨(dú)一無(wú)二的,對(duì)此我對(duì)shiro對(duì)于權(quán)限標(biāo)簽的校驗(yàn)產(chǎn)生了興趣,查看源碼,一路debug后最終在org.apache.shiro.authz.permission中看到了關(guān)鍵所在,核心代碼如下

//當(dāng)這個(gè)方法返回true時(shí)說(shuō)明有此權(quán)限
//這個(gè)p是代表當(dāng)前循環(huán)匹配到的權(quán)限標(biāo)簽
public boolean implies(Permission p) {
// By default only supports comparisons with other WildcardPermissions
if (!(p instanceof WildcardPermission)) {
return false;
}
    WildcardPermission wp = (WildcardPermission) p;
 //把當(dāng)前標(biāo)簽轉(zhuǎn)分割成一個(gè)set集合(如one:page1:view:add 會(huì)分割成[[one], [page1], [view], [add]])
    List<Set<String>> otherParts = wp.getParts();
    int i = 0;
 //循環(huán)匹配權(quán)限標(biāo)簽
    for (Set<String> otherPart : otherParts) {
        // If this permission has less parts than the other permission, everything after the number of parts contained
        // in this permission is automatically implied, so return true
  //當(dāng)全部循環(huán)匹配完沒(méi)有返回false,則返回true,這個(gè)getparts()方法是獲取當(dāng)前角色當(dāng)前循環(huán)的權(quán)限標(biāo)簽([[one], [page1], [view]])
        if (getParts().size() - 1 < i) {
            return true;
        } else {
            Set<String> part = getParts().get(i);
   /*如果包含有‘*'而且不包含當(dāng)前分割后的標(biāo)簽則返回false,
    *當(dāng)用戶可以查看頁(yè)面,也就是說(shuō)當(dāng)前角色擁有one:page1:view標(biāo)簽
    *這里【!part.contains(WILDCARD_TOKEN)】返回true,第二個(gè)【part.containsAll(otherPart)】one會(huì)跟當(dāng)前標(biāo)簽匹**配one,
    *也就是說(shuō)這里全部循環(huán)完返回的都是false,所以最后都沒(méi)true,于是在上面返回了一個(gè)true。
            if (!part.contains(WILDCARD_TOKEN) && !part.containsAll(otherPart)) {
                return false;
            }
            i++;
        }
    }

小結(jié)一下:通過(guò)分析,我們看到了shiro在定義權(quán)限標(biāo)簽時(shí),要主意匹配問(wèn)題,不要存在包含問(wèn)題,類似aaa 和aaab ,會(huì)導(dǎo)致后面標(biāo)簽失效。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Mybatis分頁(yè)插件 - 示例代碼

    詳解Mybatis分頁(yè)插件 - 示例代碼

    這篇文章主要介紹了詳解Mybatis分頁(yè)插件 - 示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧。
    2016-12-12
  • Java實(shí)現(xiàn)限定時(shí)間CountDownLatch并行場(chǎng)景

    Java實(shí)現(xiàn)限定時(shí)間CountDownLatch并行場(chǎng)景

    本文將結(jié)合實(shí)例代碼,介紹Java實(shí)現(xiàn)限定時(shí)間CountDownLatch并行場(chǎng)景,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • Spring事務(wù)處理原理步驟詳解

    Spring事務(wù)處理原理步驟詳解

    這篇文章主要介紹了Spring事務(wù)處理原理步驟詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 容器環(huán)境的JVM內(nèi)存設(shè)置實(shí)踐記錄

    容器環(huán)境的JVM內(nèi)存設(shè)置實(shí)踐記錄

    Docker和K8S的興起,很多服務(wù)已經(jīng)運(yùn)行在容器環(huán)境,對(duì)于java程序,JVM設(shè)置是一個(gè)重要的環(huán)節(jié),這里總結(jié)下我們項(xiàng)目里的最佳實(shí)踐,對(duì)容器環(huán)境的JVM內(nèi)存相關(guān)知識(shí)感興趣的朋友一起看看吧
    2022-03-03
  • Java 中的 xx ≠ null 是什么新語(yǔ)法

    Java 中的 xx ≠ null 是什么新語(yǔ)法

    Java中null是一個(gè)關(guān)鍵字,用來(lái)標(biāo)識(shí)一個(gè)不確定的對(duì)象。因此可以將null賦給引用類型變量,但不可以將null賦給基本類型變量。本文給大家分享Java 中的 xx ≠ null 是什么新語(yǔ)法,感興趣的朋友一起看看吧
    2021-06-06
  • java 數(shù)據(jù)結(jié)構(gòu)基本算法希爾排序

    java 數(shù)據(jù)結(jié)構(gòu)基本算法希爾排序

    這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)基本算法希爾排序的相關(guān)資料,需要的朋友可以參考下
    2017-08-08
  • Maven?Repository?使用方法

    Maven?Repository?使用方法

    對(duì)于Java開(kāi)發(fā)者來(lái)說(shuō),Maven?Repository是個(gè)必須掌握的網(wǎng)站,它可以讓開(kāi)發(fā)者更加方便地管理和維護(hù)?Java?項(xiàng)目的依賴項(xiàng),同時(shí)簡(jiǎn)化了項(xiàng)目開(kāi)發(fā)的過(guò)程,這篇文章主要介紹了Maven?Repository?使用方法,需要的朋友可以參考下
    2024-02-02
  • 基于Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的數(shù)據(jù)同步組件

    基于Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的數(shù)據(jù)同步組件

    這篇文章主要為大家詳細(xì)介紹了如何基于Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的數(shù)據(jù)同步組件,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解一下
    2023-06-06
  • SpringBoot淺析安全管理之高級(jí)配置

    SpringBoot淺析安全管理之高級(jí)配置

    安全管理是軟件系統(tǒng)必不可少的的功能。根據(jù)經(jīng)典的“墨菲定律”——凡是可能,總會(huì)發(fā)生。如果系統(tǒng)存在安全隱患,最終必然會(huì)出現(xiàn)問(wèn)題,這篇文章主要介紹了SpringBoot安全管理之高級(jí)配置
    2022-08-08
  • java實(shí)現(xiàn)文件復(fù)制、剪切文件和刪除示例

    java實(shí)現(xiàn)文件復(fù)制、剪切文件和刪除示例

    這篇文章主要介紹了java實(shí)現(xiàn)文件復(fù)制、剪切文件和刪除示例,需要的朋友可以參考下
    2014-04-04

最新評(píng)論

监利县| 刚察县| 望江县| 花莲县| 南华县| 广德县| 肥城市| 拉萨市| 曲沃县| 拜泉县| 星座| 宣恩县| 鄯善县| 明水县| 海城市| 财经| 和田市| 绥德县| 麻城市| 广东省| 新沂市| 子洲县| 上蔡县| 大同市| 德庆县| 瓦房店市| 申扎县| 富裕县| 白沙| 白银市| 湘乡市| 仙游县| 德钦县| 讷河市| 惠东县| 英超| 中牟县| 泊头市| 广汉市| 明光市| 青州市|