报错讯息
使用Spring Cloud + Spring Security Oauth2.0 + JWT 做分布式认证的时候,内部微服务调用的时候出现权限问题。
feign.FeignException$Unauthorized: [401] during [POST] to [http://authorization-server/oauth/token?grant_type=password&username=admin&password=123456&login_type=admin_type] [OAuth2FeignClient#getToken(String,String,String,String,String)]: [{"error":"unauthorized","error_description":"A granted authority textual representation is required"}]
at feign.FeignException.clientErrorStatus(FeignException.java:197) ~[feign-core-10.10.1.jar:na]
at feign.FeignException.errorStatus(FeignException.java:177) ~[feign-core-10.10.1.jar:na]
at feign.FeignException.errorStatus(FeignException.java:169) ~[feign-core-10.10.1.jar:na]
at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:92) ~[feign-core-10.10.1.jar:na]
at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:96) ~[feign-core-10.10.1.jar:na]
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:138) ~[feign-core-10.10.1.jar:na]
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89) ~[feign-core-10.10.1.jar:na]
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) ~[feign-core-10.10.1.jar:na]
at com.sun.proxy.$Proxy167.getToken(Unknown Source) ~[na:na]
at com.casey.service.impl.SysLoginServiceImpl.login(SysLoginServiceImpl.java:60) ~[classes/:na]
at com.casey.controller.SysLoginController.login(SysLoginController.java:39) ~[classes/:na]
可能的说法
网上查了说缺这个。但我已经有了。
这种情况为没有认证就请求了资源服务器的资源,解决办法为使用Feign的时候把请求的认证信息传递过去,或者资源服务那边开放一些接口。不过开放接口的话情况有点多,所以就选择把token携带过去了。feign提供了一个名为RequestInterceptor得拦截器,可以在请求的时候指定请求头。
@Slf4j
public class OAuth2FeignConfig implements RequestInterceptor {
// 在每一个请求里面,都会被调用
@Override
public void apply(RequestTemplate requestTemplate) {
// 1. 可以藏 request 的上下文环境获取 token
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if(requestAttributes == null){
log.info("没有请求的上下文,故无法进行token的传递");
}
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
String header = request.getHeader(HttpHeaders.AUTHORIZATION); // 获取请求上下文的头里面的AUTHORIZATION
if(!StringUtils.isEmpty(header)){
// token 传递
requestTemplate.header(HttpHeaders.AUTHORIZATION, header);
log.info("本次token传递成功,token值为{}", header);
}
}
}
解决方案
最后发现是数据库的权限表错手删除了。补上就好了,应该是查完拿了个 null 就有问题了。
参考
Feign调用出现权限问题 feign.FeignException$Unauthorized: [401] during [GET] to[…]