【Shiro】Shiro从小白到大神(三)-权限认证(授权)-1

本文涉及的产品
访问控制,不限时长
简介: 【Shiro】Shiro从小白到大神(三)-权限认证(授权)-1

本节讲权限认证,也就是授权

基于角色的访问控制和基于权限的访问控制的小实例

以及注解式授权和JSP标签授权详解


权限认证


权限认证核心要素


权限认证,也就是访问控制,即在应用中控制谁能访问哪些资源

在权限认证中,最核心的三个要素是:权限,角色和用户 (资源也算一个要素,但不是最核心的)

权限,即操作资源的 权限,比如访问某个页面,以及对某个模块的数据的添加,修改,删除,查看的权利(整合以后,其实就是一些对URL请求的权限)

角色,是权限的集合,一种角色可以包含多种权限(将权限赋给角色)

用户,在Shiro中,代表访问系统的用户,即Subject(将角色赋给用户)

英文好的,可以去看官方文档介绍: http://shiro.apache.org/authorization.html


授权




编程式授权(Programmatic Authorization)


—-基于角色的访问控制


首先配置ini文件:


[users]
;基于角色的访问控制的配置文件
chx=123456,role1,role2
;加角色,密码后面是拥有的角色
jack=123456,role1

测试类

package cn.chenhaoxiang.shiro;
import cn.chenhaoxiang.common.ShiroUtils;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
/**
 * 基于角色的访问控制
 */
public class RoleTest {
    private static Logger logger = LoggerFactory.getLogger(RoleTest.class);
    /**
     * hasRole(String roleName)  Returns true if the Subject is assigned the specified role, false otherwise.
     * hasRoles(List<String> roleNames) Returns a array of hasRole results corresponding to the indices in the method argument. Useful as a performance enhancement if many role checks need to be performed (e.g. when customizing a complex view)
     * hasAllRoles(Collection<String> roleNames) Returns true if the Subject is assigned all of the specified roles, false otherwise.
     * hasRole 判断是否拥有某个角色
     *
     * hasRoles 判断拥有某个角色  返回的是boolean[]  用来高效判断对应角色拥有
     * hasAllRoles 判断拥有所有角色  拥有传入的全部角色的话,才返回true
     *
     */
    @Test
    public void testHasRole(){
        Subject subject = ShiroUtils.login("classpath:shiro_role.ini","chx","123456");
        logger.info(subject.hasRole("role1")?"有role1这个角色":"没有role1这个角色");
        logger.info(subject.hasRole("role2")?"有role2这个角色":"没有role2这个角色");
        Subject subject2 = ShiroUtils.login("classpath:shiro_role.ini","jack","123456");
        logger.info(subject2.hasRole("role1")?"有role1这个角色":"没有role1这个角色");
        logger.info(subject2.hasRole("role2")?"有role2这个角色":"没有role2这个角色");
        // hasRoles 判断拥有某个角色  返回的是boolean[]  用来高效判断对应角色拥有
        boolean[] results = subject.hasRoles(Arrays.asList("role1","role2","role3"));
        logger.info(results[0]?"有role1这个角色":"没有role1这个角色");
        logger.info(results[1]?"有role2这个角色":"没有role2这个角色");
        logger.info(results[2]?"有role2这个角色":"没有role3这个角色");
        //hasAllRoles 判断拥有所有角色  拥有传入的全部角色的话,才返回true
        logger.info(subject.hasAllRoles(Arrays.asList("role1","role2"))?"有role1和role2这两个个角色":"role1,role2这两个角色不全部有");
        subject.logout();//退出
    }
    /**
     * CheckRole
     */
    @Test
    public void testCheckRole(){
        Subject subject = ShiroUtils.login("classpath:shiro_role.ini","chx","123456");
        subject.checkRole("role1");//没有返回值
        //subject.checkRole("role3");//没有这个角色会抛出异常 //org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role211]
        //checkRoles(Collection<String> roleNames)
        subject.checkRoles(Arrays.asList("role1","role2"));
        //subject.checkRoles(Arrays.asList("role1","role2","role3"));//没有全部角色会抛出异常 //org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role3]
        //checkRoles(String... roleNames)和checkRoles(Collection<String> roleNames)意思一样,传入的参数类型不同
        subject.checkRoles("role1","role2");
        subject.logout();//退出
    }
}

演示结果自己跑一遍就出来啦

—-基于权限的访问控制

配置ini文件:

[users]
;基于权限的访问控制的配置文件
chx=123456,role1,role2
;加角色,密码后面是拥有的角色
jack=123456,role1
[roles]
;不判断角色,直接判断权限
role1=user:select
;role1拥有select权限 这里的user:select权限名字是自己定义的
role2=user:add,user:update,user:delete
;权限无非就是增删改查

测试类:

package cn.chenhaoxiang.shiro;
import cn.chenhaoxiang.common.ShiroUtils;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 基于权限的访问控制
 */
public class PermissionTest {
    private static Logger logger = LoggerFactory.getLogger(PermissionTest.class);
    /**
     * isPermitted(Permission p)  isPermitted(String str)  如果是拥有访问某个资源的权限,返回true  单个权限判断
     *
     * isPermitted(String... var1);  分别判断多个权限  返回boolean[]
     *
     * isPermittedAll(String... var1);  拥有所有权限才返回true
     */
    @Test
    public void testIsPermitted(){
        //Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","chx","123456");
        Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","jack","123456");
        logger.info(subject.isPermitted("user:select")?"有user:select权限":"没有user:select权限");
        logger.info(subject.isPermitted("user:update")?"有user:update权限":"没有user:update权限");
        boolean results[] = subject.isPermitted("user:select","user:update","user:delete");
        logger.info(results[0]?"有user:select权限":"没有user:select权限");
        logger.info(results[1]?"有user:update权限":"没有user:update权限");
        logger.info(results[2]?"有user:delete权限":"没有user:delete权限");
        logger.info(subject.isPermittedAll("user:select","user:update")?"有user:select和user:update权限":"user:select和user:update权限不全有");
        subject.logout();//退出
    }
    /**
     *
     * checkPermission(String var1)  没有这一个权限就抛出异常
     * checkPermissions(String... var1)  没有这些权限就抛出异常
     */
    @Test
    public void testCheckPermitted(){
        //Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","chx","123456");
        Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","jack","123456");
        subject.checkPermission("user:select");//检查是否有某个权限  没有权限则抛出异常
        //subject.checkPermission("user:delete");//org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [user:delete]
        subject.checkPermissions("user:select","user:update");
        subject.logout();//退出
    }
}

讲了几个org.apache.shiro.subject.Subject的函数。

其实官方文档都有介绍的


注解式授权


更加详细的介绍可以去官网查看: http://shiro.apache.org/authorization.html


首先你的Java版本5+才能集成shiro的注解


RequiresAuthentication注解


RequiresAuthentication注解需要在当前会话中对当前的Subject进行身份验证,以便访问或调用该注解的类/实例/方法。

也就是要求当前Subject已经在当前的Session中被验证通过才能被访问或调用

比如:


@RequiresAuthentication //判断验证有没有通过
public void updateAccount(Account userAccount) {
    //this method will only be invoked by a
    //Subject that is guaranteed authenticated
    ...
}

基本等同于下面的代码:


public void updateAccount(Account userAccount) {
    if (!SecurityUtils.getSubject().isAuthenticated()) {
        throw new AuthorizationException(...);
    }
    //Subject is guaranteed authenticated here
    ...
}

RequiresGuest注解

要求当前的Subject是一个’guest’(游客),也就是说,必须是在之前的session中没有被验证或被记住才能被访问和调用

例如:

@RequiresGuest
public void signUp(User newUser) {
    //this method will only be invoked by a
    //Subject that is unknown/anonymous
    ...
}

基本等价于下面的代码:


public void signUp(User newUser) {
    Subject currentUser = SecurityUtils.getSubject();
    PrincipalCollection principals = currentUser.getPrincipals();
    if (principals != null && !principals.isEmpty()) {
        //known identity - not a guest:
        throw new AuthorizationException(...);
    }
    //Subject is guaranteed to be a 'guest' here
    ...
}

RequiresPermissions注解


RequiresPermissions注解要求当前Subject允许一个或多个权限来执行带注释的方法。

也就是说,必须有这个权限才能访问

例如:


@RequiresPermissions("account:create") //必须有account:create权限,多个权限之间用逗号隔开
public void createAccount(Account account) {
    //this method will only be invoked by a Subject
    //that is permitted to create an account
    ...
}


基本等价于:


public void createAccount(Account account) {
    Subject currentUser = SecurityUtils.getSubject();
    if (!subject.isPermitted("account:create")) {
        throw new AuthorizationException(...);
    }
    //Subject is guaranteed to be permitted here
    ...
}


相关实践学习
消息队列+Serverless+Tablestore:实现高弹性的电商订单系统
基于消息队列以及函数计算,快速部署一个高弹性的商品订单系统,能够应对抢购场景下的高并发情况。
云安全基础课 - 访问控制概述
课程大纲 课程目标和内容介绍视频时长 访问控制概述视频时长 身份标识和认证技术视频时长 授权机制视频时长 访问控制的常见攻击视频时长
目录
相关文章
|
6月前
|
数据库
shiro认证和授权
shiro认证和授权
52 3
|
6月前
|
Java 数据安全/隐私保护
Shiro - 授权那些事
Shiro - 授权那些事
51 0
|
6月前
|
缓存 安全 数据安全/隐私保护
Shiro - 认证那些事
Shiro - 认证那些事
43 0
|
JSON 前端开发 数据格式
SpringSecurity基础-认证授权结果处理
在传统的应用中,认证成功后页面需要跳转到认证成功页面或者跳转到个人中心页,但是在前后端分离的项目通常是使用Ajax请求完成认证,这时候我们需要返回一个JSON结果告知前端认证结果,然后前端自行跳转页面。 要做到上述功能,我们需要自定义认证成功处理器实现AuthenticationSuccessHandler接口复写 onAuthenticationSuccess方法,该方法其中一个参数是Authentication ,他里面封装了认证信息,用户信息UserDetails等,我们需要在这个方法中使用Response写出json数据即可
134 0
|
JSON 前端开发 数据格式
六.SpringSecurity基础-认证授权结果处理
SpringSecurity基础-认证授权结果处理
|
安全 Java 数据库连接
【Shiro】1、Shiro实现登录授权认证功能(上)
之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧
311 0
|
Java 数据安全/隐私保护
【Shiro】1、Shiro实现登录授权认证功能(中)
之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧
130 0
|
Java 数据安全/隐私保护
【Shiro】1、Shiro实现登录授权认证功能(下)
之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧
135 0
|
网络安全 数据库 数据安全/隐私保护
Shiro自定义Realm实现认证和授权(五)下
Shiro自定义Realm实现认证和授权(五)
158 0
Shiro自定义Realm实现认证和授权(五)下
|
缓存 数据库 数据安全/隐私保护
Shiro自定义Realm实现认证和授权(五)上
Shiro自定义Realm实现认证和授权(五)
345 0
Shiro自定义Realm实现认证和授权(五)上