Shiro_02_基础概念

something before start

shiro有很多的概念命名其实是面向安全框架领域的,有一些和我们日常生活中的常用词不太一样,不过好在都很容易找到相近含义的词汇。
入门过程最好是配合代码一起学习,这是我的Shiro学习Demo仓库,非常建议开始看博客前先把代码运行起来。

基础概念

Subject

Subject:用户的安全视图(a security-specific “view” of an application User.),可以简单理解为User、当前与应用交互的对象。

// 获得当前用户
Subject currentUser = SecurityUtils.getSubject();

使用SecurityUtils.getSubject()即可获取当前的Subject
在单机环境下,Subject基于应用中的用户数据
在Web环境下,Subject基于请求(request)或者当前的线程

session

Session:类似于HttpSession,但是shiro的会话不依赖于HTTP环境

        // 获取当前的session
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("Retrieved the correct value! [" + value + "]");
        }

获取了当前用户之后,就可以得到当前用户的会话(session)并进行读写操作。
在non-Web环境下,shiro默认会使用它的企业级Session管理器(Enterprise Session Management)
在Web环境下,shiro的session则基于HttpSession

认证

认证:明确用户的身份,从用户的角度来讲叫做登陆
得到当前的Subject(用户)之后,我们就可以对其进行身份认证。
下面介绍两个关于身份认证的概念 tokenrealm

token

token:令牌,一般我们常见的username-password就是一种令牌。shiro中有自带了几种默认令牌,如果有需要的话我们可以通过实现AuthenticationToken接口来自定义令牌。

UsernamePasswordToken token = new UsernamePasswordToken("guest", "guest");

realm

realm:用于存储关于用户的安全数据的组件。同时也是对token进行校验的地方
shiro通过realm来获取用户的安全信息,比如账号密码,用户的身份(role),可以进行的操作(pemission)。
realm可以和数据库、系统文件等进行交互,它使得shiro和底层数据存储耦合度降低,可以根据用户的需求来选择安全数据存储在什么地方。
在本项目中,使用了shiro.ini文件来配置realm。//该方法简单看看明白大概是什么意思就行,没必要深究

# 配置用户的账号密码
[users]
# 用户 root 密码为secret,角色为admin
root = secret, admin
guest = guest, guest
# 用户 lonestarr 密码为vespa,角色为goodguy和schwartz
lonestarr = vespa, goodguy, schwartz

# role设置,左边是role,右边是permission
# permission有规范的语法,详情看后面的博客,这里暂时只做简单的理解
# ‘:’为层级分隔符,‘*’为通配符
[roles]
# 'admin' role(身份) 有所有种类的 permissions(操作权限),*为通配符
admin = *
# The 'schwartz' role 可以做任何以 lightsaber: 开头的权限
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5

一些关于认证的操作

currentUser.isAuthenticated():判断当前用户是否已经被授权
currentUser.login(token);:根据token进行登陆.
如果校验通过,则当前用户状态变更为已认证,isAuthenticated()返回true
如果校验失败,则抛出异常

        // 登陆测试
        if (!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken("guest", "guest");
//            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);
            try {
                currentUser.login(token);
            } catch (UnknownAccountException uae) {
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

logout

currentUser.logout();:会把这次会话中的临时信息删除干净,比如session。然后清除当前用户的认证状态

授权

授权:让特定的用户进行某种操作.

role

role:角色,常见的role有adminguest

permission

permission:操作权限,一般以操作命名。常见操作权限即增删改查权限。
支持不同的层级,以:作为分割。支持通配符*
举几个例子来做简单理解:
book:query``book:add``book:delete:对书进行搜索、增加、查询操作
book:*:对书本可以有任何的操作
*:add:对任何主体都可以进行增加操作
book:add:store1:对store1仓库的书进行增加
book:*:store1:对store1仓库的书进行任何的操作
另外,末尾的*可以缺省
如:book 等价于 book:*:*

因为它的permission校验不是简单的字符串比对,它会根据一定的格式对字符串进行拆分之后在进行对比,后面的博客会简单看看他的对比逻辑

一些关于授权的操作

currentUser.hasRole("schwartz")
currentUser.isPermitted("lightsaber:wield")

SecurityManager

shiro的核心部件,将各个组件组合到一起,然后将对应的接口提供给Subject

其他一些组件

因为涉及到一些源码流程的内容,这里只是简单提及。
Authenticator 认证器
Authorizer 授权器
Authentication Strategy 授权策略
SessionManager session管理器
SessionDAO session数据存取器
CacheManager 缓存管理器
Cryptography 密码器

posted @ 2021-02-20 00:10  sarise  阅读(46)  评论(0编辑  收藏  举报