适合环境:
微服务项目:springboot/cloud docker 集成开发环境
架构:使用网关对每个服务进行路径映射分配,使用Security oauth对服务调用接口时进行权限认证,该认证加了(Authorization)。
我的逻辑:
JAVA后端使用定时任务每30分钟执行一次,该任务中包含了Feign远程调用其它服务得接口,自此该bug出现。
Bug/Exception(异常过程)
第一步:定时任务执行
//设置每隔30分钟执行一次
@Scheduled(cron = "0 0/30 * * * ?")
public void ziliZuRu() {
try {
ziLiDataTypeService.addPlan();
} catch (Exception e) {
e.printStackTrace();
}
}
第二步:service逻辑层(引用feign调用接口,获得数据)
注入Feign接口
@Autowired
private ResourcesServiceApi resourcesServiceApi;
@Transactional
public void addPlan() throws Exception{
//调用方法获得数据
/**
*就是这里出现问题了
*原因:微服务在调用其它服务接口时必须携带有Http Authroation认证过得tocken
*否则,就会抛出401异常
**/
Map<String, Long> allMaterialId = resourcesServiceApi.getAllMaterialId();
}
异常如下:
描述:该异常表示,访问远程接口时你没有权限访问,也就是你并没有将tocken给它
解决过程
设置拦截器:(并没有什么用,错误该出还出,原来以为tocken在登陆时,就已经保存在域当中了,并没有)
描述:该拦截器,拦截没有带tocken的请求,并为其加上tocken,可是tocken并没有保存在域当中,这个拦截器无效。
为何?因为定时任务是后端自动开启,并没有前端介入,之前你所有接口都管用是因为你在执行时前端就已经帮你把tocken给拼上去了,这个定时任务不会。所以造成了错误。!!!
/**
* 为Feign添加拦截器
*/
@Configuration
public class FeignConfig implements RequestInterceptor {
public void apply(RequestTemplate requestTemplate){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
//添加token
// request.getParameter("access_token"):从请求参数中获取access_token的值
// query方法:修改请求路径 并添加参数
requestTemplate.query("access_token",request.getParameter("access_token"));
}
}
}
调试该拦截器如图所示:这就是null,所以此时的tocken根本就没有存在域当中
百度又说,为null的原因就是你没有将RequestContextHolder注入spring容器当中(然而试了又没有用,该null还null)
到这里,我中间试了多次,还是不行,一天半就这样过去了。停留在原地,一点没动。。。
第二天继续搞
从一个架构师口中得知,你可以尝试直接使用用户的身份在登陆时,就拿到该tocken。
OK~ 换方法
试了一上午,各种百度springboot实时获得tocken。。。。。 没用!!!!!
后来一想,微服务除了网关,它还有Authorization (Basic)权限认证,那个账号密码可是重中之重!!!
怼~~~~~~~~~~~~~~~~~~
借鉴以前公司同事所说~~~~~~~
下午来了~~~~~~~~~~~~~~~~!!!!!!!!!!!!!
先搞个工具类,该工具类没别的想法,就为了拿到tocken
public class findTokenUtil {
public String getTocken(){
Map<String, String> map =null;
try {
//我的url 例子 供你参考
URL url = new URL ("http://这是你的url:这是你的网关端口/后面是你的路径?这后面跟上你的用户名账号和密码");
String encoding = Base64.getEncoder().encodeToString(("Authorization账号:Authorization密码").getBytes("UTF-8"));
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty ("Authorization", "Basic " + encoding);
InputStream content = (InputStream)connection.getInputStream();
BufferedReader in =
new BufferedReader (new InputStreamReader (content));
String line;
while ((line = in.readLine()) != null) {
JSONObject jasonObject = JSONObject.parseObject(line);
map = (Map) jasonObject;
}
} catch(Exception e) {
e.printStackTrace();
}
return map.get("access_token");
}
}
我的url和Authorization供你参考一下
url
//IP 想必你肯定了解 这里就不写出来了 不然小危险~~~~
http://ip:5555/api/uaa/oauth/token?grant_type=password&username=admin&password=admin
Authorization
//我的Authorization 项目设置的认证 就是
//账号 android
//密码 android00
String encoding = Base64.getEncoder().encodeToString(("android:android00").getBytes("UTF-8"));
一运行 心里那个激动 两天 就为了拿到这一串!!!!
389fe4d9-8086-4909-9492-d730af55d103
如果有什么问题的!联系我QQ:2509647976 微信:x331191249
另外 寻求 微服务好友 一块儿成长!!!!