背景
某项目在weblogic升级失败后进行回滚,回滚后环境接口无法访问,报500异常,接口为BPM Service客户端程序,错误如下:
SEVERE: <.> getTokenType: invalid token: e0FFU31EbGdrK0IxSlV1WkFMM0doc2dlMUJxdWpjQmEza0tzZGNncnlOSUlLdnFaT0QrY1pyanBBa0d0MTdURHhqbmx4SWJ1d3hvMGsxNmZyaUJFcDIvbGd3MkFWUjRCUXVZdFhvemcxZmprQm83akFoS3pMSWVxeG1DT213VkJpUW5rUWhzQ3lVSmRUT204dXdUUmI2bnlsdEg4bTducTFBWVd0eDVKWjdVSHRiRndsRkRxcjQrZnBVKzBoV0lkc1lRZXQ2VlZkSDRtNUp0V05LYW1SdGNMNWZOUE0rVTVtaEhYYWU5czg4c1VLNHIvenFDN05GTXFieGl6YXJubkd6ZHhTSEZRcUxiRTlmK3ZaNzlLMVlCNExmbkJhL0pSY2hvanlHZ0ZyQWJLdVhJbz0=
SEVERE: <.> Invalid Token Error in Verification Service.
Invalid Token Error in Verification Service. Received invalid token in getTokenType.
Verify that correct token is passed.
ORABPEL-30503
Invalid Token Error in Verification Service.
Invalid Token Error in Verification Service. Received invalid token in getTokenType.
Verify that correct token is passed.
at oracle.bpel.services.workflow.verification.impl.Token.getTokenType(Token.java:545)
at oracle.bpel.services.workflow.verification.impl.Token.isSameValue(Token.java:314)
at oracle.bpel.services.workflow.verification.impl.VerificationService.isInternalWorkflowContext(VerificationService.java:689)
排查
从错误日志上看是token问题,首先就要搞清楚token是怎么来的,经过排查,整理出token的逻辑如下
- 1.用户在登录页输入用户名密码登录
- 2.后台登录bpm获取token
- 3.bpm token经过加密后作为jwt的claim放入jwt token中
- 4.用户带上jwt token获取代办
- 5.后台解码jwt token,从jwt中获取bpm token的claim
- 6.解密bpm token
- 7.带上bpm token调用bpm api
还有一个比较重要的信息是,登录获取token的接口和调用bpm api的接口不在同一个war包里,所以一开始怀疑是两边bpm相关jar包版本不一样,比如登录生成token用的jar包和调用bpm api用的jar包如果版本不一样,那么token就可能无法被识别,然后都是朝着这个方向去排查,试了很多方案
- 两边都将依赖通过 library-ref方式引用soa.workflow库
- 两个接口放入同一个war包
- 两边都通过直接引入bpm-service.jar包方式调用bpm api
以上方式都失败后,回过头来看错误日志
Invalid Token Error in Verification Service.
Invalid Token Error in Verification Service. Received invalid token in getTokenType.
Verify that correct token is passed.
at oracle.bpel.services.workflow.verification.impl.Token.getTokenType(Token.java:545)
at oracle.bpel.services.workflow.verification.impl.Token.isSameValue(Token.java:314)
at oracle.bpel.services.workflow.verification.impl.VerificationService.isInternalWorkflowContext(VerificationService.java:689)
因为该项目的后台我们没有权限,因此也用不了arthas进行调试,但还是通过其他环境找到了oracle.bpel.services.workflow.verification.impl.Token.getTokenType(Token.java:545)
所在的jar包位置${SOA_HOME}/soa/modules/oracle.soa.workflow_11.1.1/bpm-services.jar
,代码如下
public static Type getTokenType(String token) throws WorkflowException {
if (token == null)
throw new WorkflowException(new IllegalArgumentException());
List<String> tokenList = CommonUtil.split(token, ";;");
Type type = Type.GENERIC;
if (tokenList != null && tokenList.size() < 3) {
Object[] errorObjs = {"getTokenType"};
DiagnosticService.log(18, DiagnosticService.DIAGNOSTICS_ERRORS, "getTokenType: invalid token: " + token);
throw new WorkflowException(30503, errorObjs);
}
String typeStr = tokenList.get(1);
if (Type.GENERIC.toString().equals(typeStr))
return Type.GENERIC;
if (Type.INTERNAL.toString().equals(typeStr))
return Type.INTERNAL;
if (Type.TASKFLOW_INTERNAL.toString().equals(typeStr))
return Type.TASKFLOW_INTERNAL;
return Type.GENERIC;
}
比较核心的代码是以下两行
List<String> tokenList = CommonUtil.split(token, ";;");
if (tokenList != null && tokenList.size() < 3) {
Object[] errorObjs = {"getTokenType"};
DiagnosticService.log(18, DiagnosticService.DIAGNOSTICS_ERRORS, "getTokenType: invalid token: " + token);
throw new WorkflowException(30503, errorObjs);
}
对token使用分隔符;;
进行切割,如果长度小于3那么就会抛出30503异常和错误日志一样,但从日志中我们可以看到token为
e0FFU31EbGdrK0IxSlV1WkFMM0doc2dlMUJxdWpjQmEza0tzZGNncnlOSUlLdnFaT0QrY1pyanBBa0d0MTdURHhqbmx4SWJ1d3hvMGsxNmZyaUJFcDIvbGd3MkFWUjRCUXVZdFhvemcxZmprQm83akFoS3pMSWVxeG1DT213VkJpUW5rUWhzQ3lVSmRUT204dXdUUmI2bnlsdEg4bTducTFBWVd0eDVKWjdVSHRiRndsRkRxcjQrZnBVKzBoV0lkc1lRZXQ2VlZkSDRtNUp0V05LYW1SdGNMNWZOUE0rVTVtaEhYYWU5czg4c1VLNHIvenFDN05GTXFieGl6YXJubkd6ZHhTSEZRcUxiRTlmK3ZaNzlLMVlCNExmbkJhL0pSY2hvanlHZ0ZyQWJLdVhJbz0=
并没有分隔符;;
,从token的流程可以看出,token是经过加密,生成token代码如下:
String wforig = ibpmCntx.getToken();
String wf = Utils.encryptUsingWLES(wforig);
wf = JWTokens.encodeBase64(wf);
claims.put("workflowContext", wf);
- encryptUsingWLES调用weblogic自身加密服务进行加密,weblogic加密可以参考之前的这篇文章
- encodeBase64是把加密过的token进行base64编码
把token按照base64解密再用weblogic解密后,也确实得到了正常的token
8b261e0a-85e7-4006-88f9-51f4a6baf887;;G;;kHUwUEZ4hbQaZATQaU1gdDDLInpm0Dv7JaDTnUyGKKSXH4qzqQtqi7k+U60mE127gPQhOxPV8M4fZLDzA6Tjm/CaBXHxboiuiNa9EB/dnxeBkU/qI0m+LUsivLbaFDiKCzhTMmGgMiqZPgxv+s3E9A==
可以看到确实包含分隔符;;
所以可以确定的是bpm client在解析token是并没有解密,下载war包反编译查看代码,确实没有解密就直接用
String wf = (String)jw.getClaim("workflowContext");
request.setProperty("workflowContext", wf);
解决
服务器上的ear和svn上的ear都没有解密的代码,最后因为几年前帮这个项目解决过问题无意中留了一个包,找到了正确的包,部署上去后问题解决
String wf = (String)jw.getClaim("workflowContext");
wf = JWTokens.decodeBase64(wf);
wf = Utils.decryptUsingWLES(wf);
request.setProperty("workflowContext", wf);
总结
如果有服务器权限实这个问题用arthas一下子就能找到问题原因,没有服务器权限的运维就是坑。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。