Shiro用户认证和用户授权流程

有时候觉得‘如约而至’是个多么美好的词,等的很辛苦,却不辜负。——《匿名》

1、引言

传统权限管理使用基于url拦截的权限管理方式,实现起来比较简单,不依赖框架,使用web提供filter就可以实现。但是这种方式存在问题,需要将将所有的url全部配置到xml中起来,有些繁琐,不易维护,url(资源)和权限表示方式不规范。
这里写图片描述
shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权。

spring中有spring security (原名Acegi),是一个权限框架,它和spring依赖过于紧密,没有shiro使用简单。

shiro不依赖于spring,shiro不仅可以实现 web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。使用shiro实现系统的权限管理,有效提高开发效率,从而降低开发成本。

2、shiro架构

这里写图片描述

  • subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。

  • securityManager:安全管理器,主体进行认证和授权都是通过securityManager进行。

  • authenticator:认证器,主体进行认证最终通过authenticator进行的。

  • authorizer:授权器,主体进行授权最终通过authorizer进行的。

  • sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套 - session管理的方式。

  • SessionDao: 通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。

  • cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。

  • realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。

注意:在realm中存储授权和认证的逻辑。

  • cryptography:密码管理,提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。比如 md5散列算法。

3、shiro认证

这里写图片描述

1、首先构造securityManager环境。
2、调用subject.login方法主体提交认证,提交的token。
3、securityManager进行认证,securityManager最终由ModularRealmAuthenticator进行认证。
4、ModularRealmAuthenticator调用IniRealm(给realm传入token) 去ini配置文件中查询用户信息
5、IniRealm根据输入的token(UsernamePasswordToken)从 shiro-first.ini查询用户信息,根据账号查询用户信息(账号和密码)
如果查询到用户信息,就给ModularRealmAuthenticator返回用户信息(账号和密码)
如果查询不到,就给ModularRealmAuthenticator返回null
6、ModularRealmAuthenticator接收IniRealm返回Authentication认证信息
如果返回的认证信息是null,ModularRealmAuthenticator抛出异常(org.apache.shiro.authc.UnknownAccountException)

如果返回的认证信息不是null(说明inirealm找到了用户),对IniRealm返回用户密码 (在ini文件中存在)和 token中的密码 进行对比,如果不一致抛出异常(org.apache.shiro.authc.IncorrectCredentialsException)

代码演示如下:

shiro-first.ini
#对用户信息进行配置
[user]
#用户账号和密码
zhangsan=111111
lisi=222222
// 用户登陆和退出
    @Test
    public void testLoginAndLogout() {
        // 创建securityManager工厂,通过ini配置文件创建securityManager工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory(
                "classpath:shiro-first.ini");

        //创建SecurityManager
        SecurityManager securityManager = factory.getInstance();

        //将securityManager设置当前的运行环境中
        SecurityUtils.setSecurityManager(securityManager);

        //从SecurityUtils里边创建一个subject
        Subject subject = SecurityUtils.getSubject();

        //在认证提交前准备token(令牌)
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "111111");

        try {
            //执行认证提交
            subject.login(token);
        } catch (AuthenticationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //是否认证通过
        boolean isAuthenticated =  subject.isAuthenticated();

        System.out.println("是否认证通过:" + isAuthenticated);

        //退出操作
        subject.logout();

        //是否认证通过
        isAuthenticated =  subject.isAuthenticated();

        System.out.println("是否认证通过:" + isAuthenticated);
    }

4、shiro授权

这里写图片描述
算法流程:
1、构造SecurityManager环境后,对subject进行授权,调用方法isPermitted(”permission串”)
2、SecurityManager执行授权,通过ModularRealmAuthorizer执行授权
3、ModularRealmAuthorizer执行realm(自定义的CustomRealm)从数据库查询权限数据
调用realm的授权方法:doGetAuthorizationInfo

4、realm从数据库查询权限数据,返回ModularRealmAuthorizer
5、ModularRealmAuthorizer调用PermissionResolver进行权限串比对
6、如果比对后,isPermitted中”permission串”在realm查询到权限数据中,说明用户访问permission串有权限,否则没有权限,抛出异常。

4.1 Shiro 支持三种方式的授权:

  • (1)编程式:通过写if/else 授权代码块完成:
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有权限
} else {
//无权限
}
  • (2)注解式:通过在执行的Java方法上放置相应
@RequiresRoles("admin")
public void hello() {
//有权限
}
  • (3)JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成:
<shiro:hasRole name="admin">
<!— 有权限—>
</shiro:hasRole>

4.2 shiro-permission.ini内容

shiro-permission.ini里边的内容相当于在数据库查询。

#用户
[users]
#用户zhang的密码是123,此用户具有role1和role2两个角色
zhang=123,role1,role2
wang=123,role2

#权限
[roles]
#角色role1对资源user拥有createupdate权限
role1=user:create,user:update
#角色role2对资源user拥有createdelete权限
role2=user:create,user:delete
#角色role3对资源user拥有create权限
role3=user:create

权限标识符号规则:资源:操作:实例(中间使用半角:分隔)
user:create:01 表示对用户资源的01实例进行create操作。
user:create:表示对用户资源进行create操作,相当于user:create:*,对所有用户资源实例进行create操作。

user:*:01 表示对用户资源实例01进行所有操作。

4.3 算法步骤演示

这里写图片描述

猜你喜欢

转载自blog.csdn.net/zhoutaochun/article/details/80330711
今日推荐