基于上一集的准备工作演示一下全局方法安全的使用方法。下面我们在数据库中创建 一个 订单表orders在项目中实现对应的实体与查询接口packagecom.kai.oauth.securityservice.entity;importlombok.Data;DatapublicclassOrder{privateStringid;privateStringordercode;privateStringuserid;privateStringorderdetails;}packagecom.kai.oauth.securityservice.mapper;importcom.kai.oauth.securityservice.entity.Order;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Select;importjava.util.List;MapperpublicinterfaceOrderMapper{Select(select * from orders where userid #{userid})publicListOrderselectOrderByUserid(Stringuserid);Select(select * from orders)publicListOrderselectAll();}创建两个空的 OrderService和 OrderControler方便做后续验证ServicepublicclassOrderService{AutowiredprivateOrderMapperorderMapper;AutowiredprivateUserMapperuserMapper;}RestControllerpublicclassOrderController{AutowiredprivateOrderServiceorderService;}方法调用授权预授权PreAuthorize在方法调用之前进行授权管理在OrderService中添加如下方法// 基于访问方法参数的检察,即 userid 等于 当前认证用户的userid才 通过认证PreAuthorize(#userid principal.id)publicListOrdergetOrders(Stringuserid){ListOrderordersorderMapper.selectOrderByUserid(userid);returnorders;}// 基于当前认证用户是否有ADMIN角色如果有 通过认证PreAuthorize(hasRole(ADMIN))publicListOrdergetOrders2(Stringuserid){ListOrderordersorderMapper.selectOrderByUserid(userid);returnorders;}//基于当前认证用户是否有delete权限如果有 通过认证PreAuthorize(hasAuthority(delete))publicListOrdergetOrders3(Stringuserid){ListOrderordersorderMapper.selectOrderByUserid(userid);returnorders;}在OrderController中暴露http端点来进行测试GetMapping(/getOrders)publicListOrdergetOrders(Stringuserid){ListOrderordersorderService.getOrders(userid);returnorders;}GetMapping(/getOrders2)publicListOrdergetOrders2(Stringuserid){ListOrderordersorderService.getOrders2(userid);returnorders;}GetMapping(/getOrders3)publicListOrdergetOrders3(Stringuserid){ListOrderordersorderService.getOrders3(userid);returnorders;}用postman分别做测试1测试/getOrders使用admin用户认证并且userid传入2 时会返回admin的订单列表但是当userid传入1 时也就是 user用户的id那么就会出现如下所示情况这就是PreAuthorize(“#userid principal.id”)这行代码的功效来限制当前登录用户只能查询自己的订单可在OrderControllerOrderService中分别打断点验证一下发现进入了 Controller 中的方法但并没有进入OrderService中的方法2 测试/getOrders2使用admin用户进行认证 无论 userid传 值 1 或是 2都可以获得订单列表使用user用户进行认证 无论 userid传 值 1 或是 2都无法获取订单列表3 测试/getOrders3 与 getOrders2方法相似可自行测试后授权PostAuthorize在方法执行完之后确定是否可以访问方法返回的结果在 OrderService 中添加两个 方法//returnObject表示方法的返回值//?[...] 是 SpEL 的集合投影filter表示筛选出符合条件的元素//userid 是返回对象如 Order 类的属性//#auth.principal.id 表示当前认证用户Authentication 对象的 ID//.size() returnObject.size()检查筛选后的集合大小是否等于原始返回值的大小//整体含义 方法的返回值中所有对象的 userid 必须等于当前登录用户的 ID否则拒绝访问。PostAuthorize(returnObject.?[userid #auth.principal.id].size() returnObject.size())publicListOrdergetOrders4(Authenticationauth){System.out.println(getOrders4进来了);ListOrderordersorderMapper.selectOrderByUserid(2);returnorders;}//检查返回值returnObject的 username 属性是否等于当前登录用户principal的用户名//不相等拒绝访问PostAuthorize(returnObject.username principal.getUsername())publicUsergetUser(Stringusername){System.out.println(getUser进来了);UseruseruserMapper.selectByUserName(username);returnuser;}在OrderController中添加 方法GetMapping(/getOrders4)publicListOrdergetOrder4(Authenticationauth){ListOrderordersorderService.getOrders4(auth);returnorders;}GetMapping(/getUser)publicStringgetUser(Stringusername){UseruserorderService.getUser(username);System.out.println(user.toString());returnuser.toString();}用postman测试 /getOrders4, 使用admin的用户进行认证时返回了结果因为代码中指定了查询的userid等于2.且返回的列表集合的总数 等于 userid2的 总数但是使用 user进行用户认证时就会出现以下问题看控制台 有 输出 getOrders4进来了的日志说明已经进入了 OrderService中的方法只是在返回时 做了拦截限制方法调用过滤预过滤PreFilter用来确定方法从输入参数中可以接收到的内容在OrderServcie中添加方法//filterObject过滤对象//过滤参数userids 只保留当前的认证用户的idPreFilter(filterObject principal.getId())publicListStringgetUserIds(ListStringuserids){returnuserids;}在OrderController中添加方法GetMapping(/getUserIds)publicListStringgetUserIds(){ListStringlistnewArrayList();list.add(1);list.add(2);listorderService.getUserIds(list);returnlist;}测试,用admin用户认证时list.add(“1”) 已经被过滤掉了后过滤PostFilter用来确定调用者在方法执行后可以从返回结果中接收到的内容在OrderServcie中添加方法//过滤结果 返回列表中 只包含当前用户的信息PostFilter(filterObject.userid principal.getId())publicListOrdergetOrders5(){ListOrderordersorderMapper.selectAll();returnorders;}在OrderController中添加方法GetMapping(/getOrders5)publicListOrdergetOrders5(){ListOrderordersorderService.getOrders5();returnorders;}测试用admin用户认证时虽然查询逻辑是selectAll 查询所有但返回的依然是 admin用户的订单信息
security第十三集 全局方法安全
基于上一集的准备工作演示一下全局方法安全的使用方法。下面我们在数据库中创建 一个 订单表orders在项目中实现对应的实体与查询接口packagecom.kai.oauth.securityservice.entity;importlombok.Data;DatapublicclassOrder{privateStringid;privateStringordercode;privateStringuserid;privateStringorderdetails;}packagecom.kai.oauth.securityservice.mapper;importcom.kai.oauth.securityservice.entity.Order;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Select;importjava.util.List;MapperpublicinterfaceOrderMapper{Select(select * from orders where userid #{userid})publicListOrderselectOrderByUserid(Stringuserid);Select(select * from orders)publicListOrderselectAll();}创建两个空的 OrderService和 OrderControler方便做后续验证ServicepublicclassOrderService{AutowiredprivateOrderMapperorderMapper;AutowiredprivateUserMapperuserMapper;}RestControllerpublicclassOrderController{AutowiredprivateOrderServiceorderService;}方法调用授权预授权PreAuthorize在方法调用之前进行授权管理在OrderService中添加如下方法// 基于访问方法参数的检察,即 userid 等于 当前认证用户的userid才 通过认证PreAuthorize(#userid principal.id)publicListOrdergetOrders(Stringuserid){ListOrderordersorderMapper.selectOrderByUserid(userid);returnorders;}// 基于当前认证用户是否有ADMIN角色如果有 通过认证PreAuthorize(hasRole(ADMIN))publicListOrdergetOrders2(Stringuserid){ListOrderordersorderMapper.selectOrderByUserid(userid);returnorders;}//基于当前认证用户是否有delete权限如果有 通过认证PreAuthorize(hasAuthority(delete))publicListOrdergetOrders3(Stringuserid){ListOrderordersorderMapper.selectOrderByUserid(userid);returnorders;}在OrderController中暴露http端点来进行测试GetMapping(/getOrders)publicListOrdergetOrders(Stringuserid){ListOrderordersorderService.getOrders(userid);returnorders;}GetMapping(/getOrders2)publicListOrdergetOrders2(Stringuserid){ListOrderordersorderService.getOrders2(userid);returnorders;}GetMapping(/getOrders3)publicListOrdergetOrders3(Stringuserid){ListOrderordersorderService.getOrders3(userid);returnorders;}用postman分别做测试1测试/getOrders使用admin用户认证并且userid传入2 时会返回admin的订单列表但是当userid传入1 时也就是 user用户的id那么就会出现如下所示情况这就是PreAuthorize(“#userid principal.id”)这行代码的功效来限制当前登录用户只能查询自己的订单可在OrderControllerOrderService中分别打断点验证一下发现进入了 Controller 中的方法但并没有进入OrderService中的方法2 测试/getOrders2使用admin用户进行认证 无论 userid传 值 1 或是 2都可以获得订单列表使用user用户进行认证 无论 userid传 值 1 或是 2都无法获取订单列表3 测试/getOrders3 与 getOrders2方法相似可自行测试后授权PostAuthorize在方法执行完之后确定是否可以访问方法返回的结果在 OrderService 中添加两个 方法//returnObject表示方法的返回值//?[...] 是 SpEL 的集合投影filter表示筛选出符合条件的元素//userid 是返回对象如 Order 类的属性//#auth.principal.id 表示当前认证用户Authentication 对象的 ID//.size() returnObject.size()检查筛选后的集合大小是否等于原始返回值的大小//整体含义 方法的返回值中所有对象的 userid 必须等于当前登录用户的 ID否则拒绝访问。PostAuthorize(returnObject.?[userid #auth.principal.id].size() returnObject.size())publicListOrdergetOrders4(Authenticationauth){System.out.println(getOrders4进来了);ListOrderordersorderMapper.selectOrderByUserid(2);returnorders;}//检查返回值returnObject的 username 属性是否等于当前登录用户principal的用户名//不相等拒绝访问PostAuthorize(returnObject.username principal.getUsername())publicUsergetUser(Stringusername){System.out.println(getUser进来了);UseruseruserMapper.selectByUserName(username);returnuser;}在OrderController中添加 方法GetMapping(/getOrders4)publicListOrdergetOrder4(Authenticationauth){ListOrderordersorderService.getOrders4(auth);returnorders;}GetMapping(/getUser)publicStringgetUser(Stringusername){UseruserorderService.getUser(username);System.out.println(user.toString());returnuser.toString();}用postman测试 /getOrders4, 使用admin的用户进行认证时返回了结果因为代码中指定了查询的userid等于2.且返回的列表集合的总数 等于 userid2的 总数但是使用 user进行用户认证时就会出现以下问题看控制台 有 输出 getOrders4进来了的日志说明已经进入了 OrderService中的方法只是在返回时 做了拦截限制方法调用过滤预过滤PreFilter用来确定方法从输入参数中可以接收到的内容在OrderServcie中添加方法//filterObject过滤对象//过滤参数userids 只保留当前的认证用户的idPreFilter(filterObject principal.getId())publicListStringgetUserIds(ListStringuserids){returnuserids;}在OrderController中添加方法GetMapping(/getUserIds)publicListStringgetUserIds(){ListStringlistnewArrayList();list.add(1);list.add(2);listorderService.getUserIds(list);returnlist;}测试,用admin用户认证时list.add(“1”) 已经被过滤掉了后过滤PostFilter用来确定调用者在方法执行后可以从返回结果中接收到的内容在OrderServcie中添加方法//过滤结果 返回列表中 只包含当前用户的信息PostFilter(filterObject.userid principal.getId())publicListOrdergetOrders5(){ListOrderordersorderMapper.selectAll();returnorders;}在OrderController中添加方法GetMapping(/getOrders5)publicListOrdergetOrders5(){ListOrderordersorderService.getOrders5();returnorders;}测试用admin用户认证时虽然查询逻辑是selectAll 查询所有但返回的依然是 admin用户的订单信息