对用户必须登陆才能访问的地址,框架中提供基于拦截器和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,
- 包含【/public】,不会强制要求用户登陆才能访问,如果用户登陆,会解析请求头中的token并将解析得到的用户信息放在请求上下文中。
- 不包含【/public】,会强制验证用户是否登陆,登陆放行,否则抛出异常
4.token续期
对于必须登陆的接口,判断token是否失效。
若失效,则抛出ACCESS_TOKEN_INVALID(10008, “无效的access token”);
若有效,对token续期。
CheckLogin
对于添加@CheckLogin的注解,会强制验证用户是否登陆,登陆放行,否则抛出异常
�UrlInterceptor
UrlInterceptor拦截器,根据配置的url进行登陆拦截。
配置了required-no-permission-url的情况下,即使登录,也不回解析用户登陆信息。
xy.core.annotation.check.login.config.enable=true
xy.core.url.interceptor.config.enable=false
xy.core.url.interceptor.config.client-id=${spring.application.name}
xy.core.url.interceptor.config.required-no-permission-url=/testa
xy.core.url.interceptor.config.required-permission-url=/*
推荐使用HeaderHandlerInterceptor方式实现。urlInterceptor会在后期版本中移除。
PreAuth
1.添加@PreAuth注解
对于需要特定权限的接口,可以在方法上添加@PreAuth(“xxx”)注解
2.校验权限
@Slf4j
@Service("preAuthService")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class PreAuthServiceImpl implements PreAuthService {
private final RedisTemplate redisTemplate;
/**
* 校验token是否过期
*
* @param userId 用户Id
* @return true:超时 false:未超时
*/
@Override
public boolean validTokenTimeOut(String userId) {
return false;
}
/**
* 校验用户是否拥有访问方法权限
*
* @param userId 用户Id
* @param permission 权限标识
* @return true:权限 false 无权限
*/
@Override
public boolean hasPermission(String userId, String permission) {
String permissionKey = XyGeneratorUtils.generatorLockKey("Permission", userId);
HashOperations hashOperations = redisTemplate.opsForHash();
if (hashOperations.hasKey(permissionKey, permission)) {
return true;
}
return true;
}
/**
* 重置用户token的有效时间
*
* @param userId 用户Id
* @param minutes token重置剩余时间,单位:分钟
*/
@Override
public void resetTokenValidTime(String userId, Integer minutes) {
String userTokenKey = XyGeneratorUtils.generatorLockKey("TokenTime", userId);
redisTemplate.opsForValue().set(userTokenKey, "1", minutes, TimeUnit.MINUTES);
}
}
此代码上升在各应用系统中,项目模版中已附带,无需开发者再次开发。
为什么上升在应用中???
应为开发过程中,开发,自测,联调过程中,可能尚未配置权限信息,方便开发人员自行控制调试。