一:权限认证出现:NotLoginException-未能读取到有效token错误
在权限认证之前,登录认证已经写完了,而且没有错误:
1.使用apifox进行登录测试
2.登录成功后会发现在Header中有set-cookie,会自动生成satoken
3.并将session和token都存到redis中
登录成功!!!
2.权限认证
①新建一个类,实现 StpInterface
接口(这里面有伏笔,错误就在这)
public class StpInterfaceImpl implements StpInterface {
@Resource
private WebAccountFeignClient webAccountFeignClient;
/**
* 返回一个账号所拥有的权限码集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
List<Dict> dictList = webAccountFeignClient.queryPermissionInfo(loginId.toString());
return dictList.stream().map(m -> m.getStr("code")).toList();
}
/**
* 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
List<Dict> dictList = webAccountFeignClient.queryRoleInfo(loginId.toString());
return dictList.stream().map(m -> m.getStr("id")).toList();
}
}
②开始对权限认证进行测试,测试类为TestController
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/select")
public String select() {
System.out.println("is login:" + StpUtil.isLogin());
System.out.println("loginId:" + StpUtil.getLoginId());
StpUtil.checkLogin();
StpUtil.getTokenValue();
System.out.println("获取权限集合" + StpUtil.getPermissionList());
return "success";
}
}
在登录的状态下,其他代码都是正确的,只有 StpUtil.getPermissionList() 是错误的,而且错误是
通过定位到这段代码--打开注解式鉴权出现了错误
@Slf4j
@EnableWebMvc
@Configuration
public class AuthModuleConfig implements WebMvcConfigurer {
/**
* 注册 Sa-Token 拦截器,打开注解式鉴权
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
log.info("AuthModule - Interceptor - SaToken");
registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin())) // 登录校验
.addPathPatterns("/**") // 拦截所有
.excludePathPatterns("/userInfo/login"); // 排除部分
}
}
这就导致我当时很蒙,因为通过checkLogin方法已经判断,登录成功了,但是一获取权限集合就出现错误,这是为什么呢?我也看过文档,搜过文章,但是还是没有成功。
注:文档的几种可能的错误--》传送门:Sa-Token
这几种错误能够解决很大部分的错误,但是没有解决掉我的问题。这里就要谈到之前的伏笔了,错误所在处,项目分成了很多的模块,我将关于satoken相关的代码都写在了auth模块中,而我在web-account模块中做的测试,所以者之间涉及到了远程调用,我使用的是fegin进行远程调用。
@Component
@FeignClient(value = "cxqx-web-account")
public interface WebAccountFeignClient {
/**
* 获取角色信息
*
*/
@LoadBalanced
@GetMapping("/roleInfo/selectRoleInfo")
List<Dict> queryRoleInfo(@RequestParam("loginId") String loginId);
/**
* 获取权限信息
*
*/
@LoadBalanced
@GetMapping("/permissionsInfo/selectPermissions")
List<Dict> queryPermissionInfo(@RequestParam("loginId") String loginId);
}
这就是错误所在之处:Feign远程调用时会丢失请求头的问题
相关的文章:Feign远程调用丢失请求头问题以及异步丢失上下文问题解决方法_lovoo的博客-CSDN博客微服务feign调用时候,token丢失问题解决方案_feign远程调用丢失token_zero _s的博客-CSDN博客
feign远程调用属于http请求,他是不会携带之前的token的,而我在没有进行feign调用的时候,登录是成功的,一进行远程调用就出现错误(等下会说到如何找到这个错误的,会涉及到satoken的一点源码),那是因为远程调用,请求了接口,被拦截了下来,需要进行登录检验,而feign请求又不会携带token,导致我出现了未获得有效token的情况。
二:我是如何发现是feign远程调用的错误呢?
此处涉及到了一些源码,我在获取权限集合的时候他总是会跳转到(satoken的好处就是国内的框架,注释是中文的)
发现getTokenValue最后返回的是null,所以我就在获取权限集合之前加了一行代码
StpUtil.getTokenValue();
首先呢,会先跳转到
之后会跳转到
进入到StpLogic下的getTokenValue()方法中,发现token值能够被获取到,并且成功的返回了
此时我就在想,既然getTokenValue()可以成功返回,但是为什么我一获取权限集合 :StpUtil.getPermissionList() 在getTokenValue() 中就会返回null呢?那么就在获取权限集合处再打个断点试试。
会先进入 StpLogic类下的getPermissionList()方法
再进入StpLogic类下的getLoginId()方法,此时的token是获取成功了的,也成功的返回了
之后会再去调用,此时参数都是正常的,我成功的获取到了
再然后就是进入到我重写的这个类中
执行这个远程调用的时候,发现再一次的跳转到
因为feign远程调用属于http请求,并且会调用一次web-account模块中的接口,所以就会被拦截器拦下,进行登录校验,而这次登录校验,并未获取到token。所以我就想到了可能是远程调用出现了问题,就去查了些资料,就是上面看到的,feign进行远程调用是不会携带原来的token的,所以登录检验失败。
那么问题找到了,就需要解决了,只需要 在拦截器中加上feign的拦截器,让他携带原来的token即可。最后问题成功的解决。
解决办法代码:
/**
* feign远程调用丢失上下文的解决方案,新增拦截器
*/
@Bean("/requestInterceptor")
public RequestInterceptor requestInterceptor() {
return (RequestTemplate requestTemplate) -> {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader("token");
String cookie = request.getHeader("Cookie");
String authorization = request.getHeader("Authorization");
requestTemplate.header("token", token);
requestTemplate.header("Cookie", cookie);
requestTemplate.header("Authorization", authorization);
}
};
}
我就马上的记录了一下这个错误,这个错误费了我接近一天的时间才解决,希望能够帮到和我出现同样错误的你!