对用户必须登陆才能访问的地址,框架中提供基于拦截器和AOP注解两种方式进行访问拦截。

登陆/权限拦截涉及以下拦截器和注解

  • HeaderHandlerInterceptor 解析token
  • @CheckLogin 通过注解强制校验是否需要登陆
  • UrlInterceptor 根据url配置校验是否要登陆
  • �PreAuth 判断用户是否有执行方法的权限

HeaderHandlerInterceptor

HeaderHandlerInterceptor主要完成以下任务:

1.initMdcTraceId

对于网关转发的请求,将网关下发的traceId同步到当前请求中。

对于非网关转发的请求,生成新的traceId到当前请求中。

2.根据请求头信息解析获取用户信息

对于网关下发的请求,从请求头中直接获取用户登陆信息并设置到当前请求线程上下文,供开发者通过UserUtil获取当前用户信息。

对于非网关下发的请求,从请求头中获取登陆token,直接解析获取用户信息并设置到当前请求线程上下文。

3.允许健康检查,swaggerApi和无需登陆的接口通过

对于非必要登陆的请求接口,直接放行。

应用中无需登陆的接口,以/public做为前缀,例如:/public/test.

默认过滤swagger,spring-actuator的健康检查接口。对于业务自定义url,

  1. 包含【/public】,不会强制要求用户登陆才能访问,如果用户登陆,会解析请求头中的token并将解析得到的用户信息放在请求上下文中。
  2. 不包含【/public】,会强制验证用户是否登陆,登陆放行,否则抛出异常

4.token续期

对于必须登陆的接口,判断token是否失效。

若失效,则抛出ACCESS_TOKEN_INVALID(10008, “无效的access token”);

若有效,对token续期。

CheckLogin

对于添加@CheckLogin的注解,会强制验证用户是否登陆,登陆放行,否则抛出异常

�UrlInterceptor

UrlInterceptor拦截器,根据配置的url进行登陆拦截。

配置了required-no-permission-url的情况下,即使登录,也不回解析用户登陆信息。
  1. xy.core.annotation.check.login.config.enable=true
  2. xy.core.url.interceptor.config.enable=false
  3. xy.core.url.interceptor.config.client-id=${spring.application.name}
  4. xy.core.url.interceptor.config.required-no-permission-url=/testa
  5. xy.core.url.interceptor.config.required-permission-url=/*

推荐使用HeaderHandlerInterceptor方式实现。urlInterceptor会在后期版本中移除。

PreAuth

1.添加@PreAuth注解

对于需要特定权限的接口,可以在方法上添加@PreAuth(“xxx”)注解

2.校验权限

  1. @Slf4j
  2. @Service("preAuthService")
  3. @RequiredArgsConstructor(onConstructor = @__(@Autowired))
  4. public class PreAuthServiceImpl implements PreAuthService {
  5. private final RedisTemplate redisTemplate;
  6. /**
  7. * 校验token是否过期
  8. *
  9. * @param userId 用户Id
  10. * @return true:超时 false:未超时
  11. */
  12. @Override
  13. public boolean validTokenTimeOut(String userId) {
  14. return false;
  15. }
  16. /**
  17. * 校验用户是否拥有访问方法权限
  18. *
  19. * @param userId 用户Id
  20. * @param permission 权限标识
  21. * @return true:权限 false 无权限
  22. */
  23. @Override
  24. public boolean hasPermission(String userId, String permission) {
  25. String permissionKey = XyGeneratorUtils.generatorLockKey("Permission", userId);
  26. HashOperations hashOperations = redisTemplate.opsForHash();
  27. if (hashOperations.hasKey(permissionKey, permission)) {
  28. return true;
  29. }
  30. return true;
  31. }
  32. /**
  33. * 重置用户token的有效时间
  34. *
  35. * @param userId 用户Id
  36. * @param minutes token重置剩余时间,单位:分钟
  37. */
  38. @Override
  39. public void resetTokenValidTime(String userId, Integer minutes) {
  40. String userTokenKey = XyGeneratorUtils.generatorLockKey("TokenTime", userId);
  41. redisTemplate.opsForValue().set(userTokenKey, "1", minutes, TimeUnit.MINUTES);
  42. }
  43. }

此代码上升在各应用系统中,项目模版中已附带,无需开发者再次开发。

为什么上升在应用中???

应为开发过程中,开发,自测,联调过程中,可能尚未配置权限信息,方便开发人员自行控制调试。