### 获取当前登录用户 ```java // 注入工具类 @Autowired private SecurityUtil securityUtil; // 获取当前登录用户【部分数据,从内存即线程线程变量中获取数据,推荐使用】 // 包含id、username、nickname、mobile、email、departmentId、type、permissions(角色和菜单名) User user = securityUtil.getCurrUserSimple(); // 获取当前登录用户【完整数据,调用SQL和Redis缓存查询】 User user = securityUtil.getCurrUser(); ``` ### 数据权限 - 获取当前用户数据权限(可访问的部门ID),返回List<String>,null代表具有所有权限 ```java // 注入工具类 @Autowired private SecurityUtil securityUtil; // 获取当前用户数据权限 List<String> ids = securityUtil.getDeparmentIds; // 获取是否仅自己数据权限 Boolean isSelfDataPerm = securityUtil.isSelfDataPerm(); ``` - 需自行根据在业务逻辑层或DAO层进行过滤使用,原理即使用SQL中的`in`语句 - JPA示例一 ```java @Override public Page<User> findByCondition(User user, Pageable pageable) { return userDao.findAll(new Specification<User>() { @Nullable @Override public Predicate toPredicate(Root<User> root, CriteriaQuery<?> cq, CriteriaBuilder cb) { Path<String> departmentIdField = root.get("departmentId"); List<Predicate> list = new ArrayList<Predicate>(); // 数据权限过滤 List<String> depIds = securityUtil.getDeparmentIds(); if(depIds!=null&&depIds.size()>0){ list.add(departmentIdField.in(depIds)); } Predicate[] arr = new Predicate[list.size()]; cq.where(list.toArray(arr)); return null; } }, pageable); } ``` - JPA示例二 ```java // DAO层 public interface UserDao extends XbootBaseDao<User, String> { List<User> findByDepartmentIdIn(List<String> departmentIds); } // 业务逻辑层 ... @Autowired private UserDao userDao; // 数据权限过滤 userDao.findByDepartmentIdIn(securityUtil.getDeparmentIds()); ... ``` - Mybatis-Plus示例 ```java ... QueryWrapper<User> qw = new QueryWrapper<User>(); // 数据权限过滤 qw.in("department_id", securityUtil.getDeparmentIds()); IPage<User> data = iUserService.page(PageUtil.initMpPage(page), qw); ... ``` ### 自定义多维度IP、uid限流示例 ```java // 注入 @Autowired private RedisRaterLimiter redisRaterLimiter; // IP限流 1秒限1个请求 String token = redisRaterLimiter.acquireToken(ip, 1, 1000); if (StrUtil.isBlank(token)) { throw new XbootException("你手速怎么这么快,请点慢一点"); } ``` ### 分布式同步锁 ```java // 注入 @Autowired private RedisLockTemplate redisLockTemplate; redisLockTemplate.execute("订单流水号", 3, TimeUnit.SECONDS, new Callback() { @Override public Object onGetLock() throws InterruptedException { // TODO 获得锁后要做的事 log.info("生成订单流水号"); return null; } @Override public Object onTimeout() throws InterruptedException { // TODO 未获取到锁(获取锁超时)后要做的事 log.info("oops 没拿到锁"); return null; } }); ``` ### Redis使用scan命令替换keys - `keys`命令效率极低,属于`O(N)`操作,会阻塞其他命令,在集群上会是灾难性的操作。XBoot框架`common`包中已提供基于`scan`操作封装的方法,详见`RedisTemplateHelper` ```java // 注入 @Autowired private RedisTemplateHelper redisTemplateHelper; // 方式一 先获取满足表达式的key 然后删除 Set<String> keys = redisTemplateHelper.scan("key::*"); redisTemplateHelper.delete(keys); // 方式二 直接通过表达式删除所有key redisTemplate.deleteByPattern("key::*"); ``` ### 第三方工具类库包`Hutool` > 已包含大量实用工具类,建议收藏仔细阅读,详见官方文档 [https://www.hutool.cn/docs/#/](https://www.hutool.cn/docs/#/) #### Xss攻击过滤 - Vue中使用`v-html`或富文本编辑器时需根据业务需求后端过滤Xss攻击,调用hutool提供的方法即可 ```java HtmlUtil.fiter("要过滤的内容") ```