一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - spring-shiro權限控制realm實戰(zhàn)教程

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

2022-02-21 13:05Moshow鄭鍇 Java教程

這篇文章主要介紹了spring-shiro權限控制realm實戰(zhàn)教程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

spring-shiro權限控制realm

用戶與角色實體

Role.java

?
1
2
3
4
5
6
7
8
9
@Data
@Entity
public class Role {
    @Id
    @GeneratedValue
    private Integer id;
    private Long userId;
    private String role;
}

User.java

?
1
2
3
4
5
6
7
8
9
@Data
@Entity
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String username;
    private String password;
}

Realm類

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

Realm.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Realm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    //授權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //從憑證中獲得用戶名
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        //根據(jù)用戶名查詢用戶對象
        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;
    }
    //認證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //獲得當前用戶的用戶名
        String username = (String) authenticationToken.getPrincipal();
        //從數(shù)據(jù)庫中根據(jù)用戶名查找用戶
        User user = userService.getUserByUserName(username);
        if (userService.getUserByUserName(username) == null) {
            throw new UnknownAccountException(
                    "沒有在本系統(tǒng)中找到對應的用戶信息。");
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(),getName());
        return info;
    }
}

Shiro 配置類

ShiroConfig.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@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>();
        //以下是過濾鏈,按順序過濾,所以/**需要放最后
        //開放的靜態(tài)資源
        filterChainDefinitionMap.put("/favicon.ico", "anon");//網(wǎng)站圖標
        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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@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("沒有足夠的權限");
        }
        return "home";
    }
    @GetMapping("/logout")
    public String logout() {
        return "index";
    }
}

Service

UserService.java

?
1
2
3
4
5
6
7
8
9
10
11
12
@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í)行本條語句");
    }
}

shiro權限不生效原因分析

shiro遇到的坑

-項目中使用shiro做登錄校驗和權限管理,在配置權限時遇到小坑,記錄一下。

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

權限標簽定義如下:

標簽定義 頁面一 頁面二
第一層級 one:view two:view
第二層級 one:page1:view two:page2:view
第三層級 one:page1:view:add two:page2:view:add

開始懷疑是數(shù)據(jù)庫沒有錄入,查看后權限標簽與角色已對應,排除。

后面懷疑是頁面問題,后面把第三層級標簽與第一二層級同一頁面,依然不起作用,排除。

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

問題原因:權限標簽定義問題

但是后來想想為什么會出現(xiàn)這種問題,每個標簽都是獨一無二的,對此我對shiro對于權限標簽的校驗產生了興趣,查看源碼,一路debug后最終在org.apache.shiro.authz.permission中看到了關鍵所在,核心代碼如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//當這個方法返回true時說明有此權限
//這個p是代表當前循環(huán)匹配到的權限標簽
public boolean implies(Permission p) {
// By default only supports comparisons with other WildcardPermissions
if (!(p instanceof WildcardPermission)) {
return false;
}
    WildcardPermission wp = (WildcardPermission) p;
 //把當前標簽轉分割成一個set集合(如one:page1:view:add 會分割成[[one], [page1], [view], [add]])
    List<Set<String>> otherParts = wp.getParts();
    int i = 0;
 //循環(huán)匹配權限標簽
    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
  //當全部循環(huán)匹配完沒有返回false,則返回true,這個getparts()方法是獲取當前角色當前循環(huán)的權限標簽([[one], [page1], [view]])
        if (getParts().size() - 1 < i) {
            return true;
        } else {
            Set<String> part = getParts().get(i);
   /*如果包含有‘*'而且不包含當前分割后的標簽則返回false,
    *當用戶可以查看頁面,也就是說當前角色擁有one:page1:view標簽
    *這里【!part.contains(WILDCARD_TOKEN)】返回true,第二個【part.containsAll(otherPart)】one會跟當前標簽匹**配one,
    *也就是說這里全部循環(huán)完返回的都是false,所以最后都沒true,于是在上面返回了一個true
            if (!part.contains(WILDCARD_TOKEN) && !part.containsAll(otherPart)) {
                return false;
            }
            i++;
        }
    }

小結一下:通過分析,我們看到了shiro在定義權限標簽時,要主意匹配問題,不要存在包含問題,類似aaa 和aaab ,會導致后面標簽失效。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://zhengkai.blog.csdn.net/article/details/80153421

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 大好硬好深好爽想要视频 | 黄网在线观看免费网站台湾swag | 亚洲精品第五页中文字幕 | 亚洲精品在看在线观看 | 国产福利自产拍在线观看 | 乌克兰粉嫩摘花第一次 | 国产大片51精品免费观看 | 免费国产福利 | 小女生RAPPER入口 | 久久福利影院 | 91麻豆精品国产片在线观看 | 午夜片神马影院福利 | www.99精品| 91高清免费国产自产 | 国产美女久久久久 | 亚洲精品国产精品国自产观看 | 亚洲成色 | 东方影库四虎 | sese在线观看 | 亚洲AV国产福利精品在现观看 | 胸奶好大好紧好湿好爽 | 亚洲AV午夜精品麻豆AV | 久久精品在现线观看免费15 | 日本道色综合久久影院 | 欧美亚洲高清日韩成人 | 久九九精品免费视频 | 久久精品热在线观看30 | 久久伊人中文字幕有码 | 国产精品麻豆 | 羞羞答答免费人成黄页在线观看国产 | 国产成人久久久精品一区二区三区 | 蜜桃影像传媒破解版 | www.国产在线观看 | 天天噜| 大伊香蕉精品二区视频在线 | 办公室的秘密在线观看 | 无限资源在线观看8 | 国产一区二区在线观看美女 | 午夜免费无码福利视频麻豆 | 久久爽狠狠添AV激情五月 | 日本捏胸吃奶视频免费 |