Shiro入门

八月加油!

shiro权限管理:
        shiro架构:

          

            securityManager:安全管理器,主体(subject)进行认证和授权。
            authenticator:认证器,主体认证所需要的。
            anthorizer:授权器,主体授权所需要的。
            sessionManager:shiro提供了一套session的管理模式。常规的session都是web容器进行统一管理。
            sessionDao:通过sessionDao来管理个性化session数据。
            cacheManager:缓存管理器,session数据和授权数据进行缓存。 -- 和ehcache整合进行缓存数据管理。
            realm:域,相当于数据源。通过realm存取认证/授权的相关数据。 -- realm中含有认证和授权逻辑。
            cryptography:加密/解密组件管理。

用户认证流程:

             
            1. 通过ini配置文件创建SecurityManager
            2. 调用subject.login方法进行主体提交认证
            3. SecurityManager最终是通过ModularRealmAuthenticator进行认证
            4. ModularRealmAuthenticator调用IniRealm去ini配置文件中查询用户信息
            5. IniRealm根据输入的token(UsernamePasswordToken)从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)

用户认证Demo:

        1.ini文件构建:采用ini文件可以实现数据分组,存储方式上和properties一致,都是采用键值对方式。

   shiro-simple.ini文件:

#用户信息分组
[users]
zhangsan=123


        2.工程搭建,采用Junit测试,书写测试用例。

//用户登录和退出认证
    @Test
    public void testLoginAndLogout(){

        //1. 通过ini文件构建SecurityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-simple.ini");

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

        //3. 将SecurityManager设置到当前的环境中
        SecurityUtils.setSecurityManager(securityManager);

        //4. 从SecurityManager中创建一个subject
        Subject subject = SecurityUtils.getSubject();

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

        try {
            //6. 执行认证提交
            subject.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }

        //7. 是否认证通过
        System.out.println("shiro--登录是否认证通过:" + subject.isAuthenticated());

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

    }

       3.测试结果:

       认证成功:

       认证失败:

      用户名未通过认证,返回Null,报org.apache.shiro.authc.UnknownAccountException异常

      密码未通过验证,报org.apache.shiro.authc.IncorrectCredentialsException异常

 

用户授权流程:

        

        1.对subject进行授权,调用方法isPermitted("permission串")。
        2.SecurityManager执行授权,通过ModularRealmAuthorizer执行授权。
     3.ModularRealmAuthorizer执行realm(自定义的CustomRealm)从数据库查询权限数据。调用realm的授权方法:doGetAuthorizationInfo。
        4.realm从数据库查询权限数据,返回ModularRealmAuthorizer。
        5.ModularRealmAuthorizer调用PermissionResolver进行权限串比对。
       6.如果比对后,isPermitted中"permission串"在realm查询到权限数据中,说明用户访问permission串有权限,否则 没有权限,抛出异常。

用户授权Demo:

        1.ini文件构建:采用ini文件可以实现数据分组,存储方式上和properties一致,都是采用键值对方式。

        shiro-permission.ini文件:

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

# 权限
[roles]
# 角色role1对资源user具有create、update权限
role1=user:create,user:update
# 角色role2对资源user具有create、delete权限
role2=user:create,user:delete


        2.工程搭建,采用Junit测试,书写测试用例。

 //角色授权,资源授权测试
    @Test
    public void testAuthorization(){

        //1. 通过ini文件构建SecurityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");

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

        //3. 将SecurityManager设置到当前的环境中
        SecurityUtils.setSecurityManager(securityManager);

        //4. 从SecurityManager中创建一个subject
        Subject subject = SecurityUtils.getSubject();

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

        try {
            //6. 执行认证提交
            subject.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }

        //7. 是否认证通过
        System.out.println("shiro--登录是否认证通过:" + subject.isAuthenticated());

        //基于角色的授权
        //hasRole传入单个角色标识
        boolean isHasRole = subject.hasRole("role1");
        //hasRole传入多个角色标识
        boolean isHasRoles = subject.hasAllRoles(Arrays.asList("role1", "role2"));
        System.out.println("单个角色判断:" + isHasRole + "\n" + "多个角色判断:" + isHasRoles);

        //使用check方法进行授权,授权不通过会抛出异常
//        subject.checkRole("role3");

        //基于资源的授权
        //isPermitted传入单个权限标识符
        boolean isPermitted = subject.isPermitted("user:create:1");
        //isPermitted传入多个权限标识符
        boolean isPermittedAll = subject.isPermittedAll("user:create", "user:delete");
        System.out.println("单个权限判断:" + isPermitted + "\n" + "多个权限判断:" + isPermittedAll);

        //使用check方法进行授权,授权不通过会抛出异常
//        subject.checkPermission("items:add");
    }

        3.测试结果:

        授权成功:

        授权失败:

自定义Realm:

       基于框架的权限管理实质上就是对数据库进行的安全管理,权限管理的操作对象均是通过Realm进行的,针对不同的需求和场景,可以自定义Realm进行权限管理。即通过Realm从数据库中获取权限数据

  CustomRealm 类:

/*
* 自定义realm -- 模拟数据库操作
* */
public class CustomRealm extends AuthorizingRealm {


    //复写命名方法
    @Override
    public void setName(String name) {
        super.setName("CustomRealm");
    }

    //用于认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        // 从token中取出身份信息
        String userCode = (String) authenticationToken.getPrincipal();

        // 根据用户输入的userCode从数据库中查询密码 -- 这里模拟数据库查询结果
        String passWord = "123";

        //查询不到返回Null

        //查询到返回认证信息AuthenticationInfo
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, passWord, this.getName());
        return simpleAuthenticationInfo;
    }

    //用于授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        //从principle中获取主体身份信息
        String userCode  = (String) principalCollection.getPrimaryPrincipal();

        //根据身份信息,获取权限信息 -- 模拟数据库连接
        List<String> permissions = new ArrayList<String>();
        permissions.add("user:create"); //用户创建权限
        permissions.add("items:add");   //商品添加权限

        //查询到权限数据,返回授权信息
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        //将授权信息添加到SimpleAuthorizationInfo中
        simpleAuthorizationInfo.addStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }
}

ini配置文件:

[main]
# 自定义realm
customRealm= com.shiro.realm.CustomRealm
# 将realm设置到SecurityManager,类比spring中的注入
securityManager.realms=$customRealm

通过自定义的Reaml可以对数据库进行权限数据获取,返回认证信息AuthenticationInfo、授权信息SimpleAuthorizationInfo。

接着就是认证/授权了,测试用例只需要在ini文件加载处进行更改。测试用例的本质就是模拟用户的操作。

//1. 通过ini文件构建SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小透明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值