Shiro入门学习四

来源:互联网 发布:如何开通淘宝 编辑:程序博客网 时间:2024/05/19 15:25

Shiro入门学习四

授权

授权流程
授权流程参考官网Authorization Sequence,也可参阅第三章 授权——《跟我学Shiro》

这里写图片描述

流程如下:

  1. 首先调用Subject.isPermitted*/hasRole*接口,其会委托给SecurityManager,而SecurityManager接着会委托给Authorizer;
  2. Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”),其首先会通过PermissionResolver把字符串转换成相应的Permission实例;
  3. 在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的角色/权限;
  4. Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRole*会返回true,否则返回false表示授权失败。

在授权中需了解的几个关键对象:

  • 主提(subject):即访问应用的用户,在Shiro中使用Subject代表该用户
  • 资源(resources):在应用中用户可以访问的任何东西
  • 权限:对某个资源的细粒度的CRUD
  • 角色:角色代表了操作集合,可以理解为权限的集合

JavaSE例子

角色

shiro.ini文件中,添加如下的内容,配置用户拥有的角色:

[users]kh=123,r1,r2zhangsan=111,r3lisi=123,r2,r3

测试如下:

    public Subject login(String username, String password) {        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");        SecurityManager securityManager = factory.getInstance();        SecurityUtils.setSecurityManager(securityManager);        Subject subject = SecurityUtils.getSubject();        UsernamePasswordToken token = new UsernamePasswordToken(username, password);        try {            subject.login(token);            return subject;        } catch (UnknownAccountException e) {            System.out.println("用户不存在");        } catch (IncorrectCredentialsException e) {            System.out.println("密码不存在");        } catch (AuthenticationException e) {            System.out.println("认证异常");        }        return null;    }    @Test    public void testRole() {        Subject subject = login("kh", "123");        System.out.println(subject.hasRole("r1"));        System.out.println(subject.hasAllRoles(Arrays.asList("r1","r2","r3")));        System.out.println(subject.hasRoles(Arrays.asList("r1","r2","r3"))[2]);        subject.checkRole("r1");    }

做一些说明:

1.hasRole("r1")是否有r1角色,返回值为boolean
2.hasAllRoles是否有所有的权限,返回值为boolean
3.hasRoles返回值为boolean为数组
4.checkRole方法没有返回值,如果没有对应的角色,则抛异常

权限

如下配置权限:

[roles]r1=user:create,user:deleter2=topic:*
  • r1=user:create,user:delete表示r1具有user的create,delete权限,可简写为r1="user:create,delete"(注意带有引号)
  • r2=topic:*表示r2具有topic的所有权限

测试如下:

    @Test    public void testPermission() {        Subject subject = login("kh", "123");        // 是否具有user的view权限 false        System.out.println(subject.isPermitted("user:view"));        // 是否具有user的delete权限 true        System.out.println(subject.isPermitted("user:delete"));        // 是否具有topic的create权限 true        System.out.println(subject.isPermitted("topic:create"));    }

如下的r1:

r1="user:create,delete","dep:del,view",classroom

classroom等同于classroom:*

r3=*:view表示r3具有任何的view的权限,如test:view,但test:abc:view则不行

自定义realm中权限的处理

可参考在Spring MVC中使用Apache Shiro安全框架

    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        //获取登录时输入的用户名        String loginName = (String) principalCollection.fromRealm(getName()).iterator().next();        //到数据库查是否有此对象        User user = this.getDao().findByName(loginName);        if (user != null) {            //权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();            //用户的角色集合            info.setRoles(user.getRolesName());            //用户的角色对应的所有权限,如果只使用角色定义访问权限,下面的四行可以不要            List<Role> roleList = user.getRoleList();            for (Role role : roleList) {                info.addStringPermissions(role.getPermissionsString());            }            return info;        }        return null;    }

授权推荐教程

  • SpringBoot+shiro整合学习之登录认证和权限控制

加密

参阅第五章 编码/加密——《跟我学Shiro》

散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等

        //202cb962ac59075b964b07152d234b70        System.out.println(new Md5Hash("123").toHex());        //ICy5YqxZB1uWSwcVLSNLcA==        System.out.println(new Md5Hash("123").toBase64());

一般进行散列时最好提供一个salt(盐),比如加密密码“admin”,产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,可以到一些md5解密网站很容易的通过散列值得到密码“admin”,即如果直接对密码进行散列相对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,如用户名和ID(即盐);这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。

String str = "hello";  String salt = "123";  String md5 = new Md5Hash(str, salt).toString();//还可以转换为 toBase64()/toHex() 
原创粉丝点击