Java使用Apache Olingo访问Dynamics 365 Business Central报Target host is null错误
问题根因
你报的Target host is null错误直接来源于你自定义认证类中模拟浏览器登录的逻辑:
- 你通过硬解析Azure AD登录页HTML提取表单提交地址、隐藏字段的实现完全不可行,Azure AD的登录页DOM结构是动态更新的,而且会根据租户配置、登录风险等因素返回不同的页面内容,你解析得到的
postURL为空/不合法,发起POST请求时没有有效目标主机就触发了该报错。 - 你的认证流程选型完全错误,Dynamics 365 Business Central对接Azure AD OAuth2不需要模拟交互登录,直接用密码授权流(ROPC)或客户端凭据流即可实现服务调用。
修复方案
1. 替换OAuth2认证逻辑
直接删掉你现有AzureADOAuth2HttpClientFactoryForDBC类中解析HTML、模拟登录的全部逻辑,改用ROPC流直接获取token,修改后的init方法如下:
@Override protected void init() throws OAuth2Exception { final DefaultHttpClient httpClient = wrapped.create(null, null); List<BasicNameValuePair> data = new ArrayList<>(); // 使用密码授权流 data.add(new BasicNameValuePair("grant_type", "password")); data.add(new BasicNameValuePair("client_id", clientId)); data.add(new BasicNameValuePair("username", creds.getUserName())); data.add(new BasicNameValuePair("password", creds.getPassword())); data.add(new BasicNameValuePair("resource", resourceURI)); // 若你注册的是私有客户端,需额外添加client_secret参数:data.add(new BasicNameValuePair("client_secret", "你的应用密钥")); fetchAccessToken(httpClient, data); if (token == null || !token.has("access_token")) { String errorMsg = token != null ? token.get("error_description").asText() : "token接口返回空响应"; throw new OAuth2Exception("获取access token失败:" + errorMsg); } }
原有fetchAccessToken、accessToken、refreshToken方法不需要修改,删掉init方法里所有解析HTML、模拟提交表单的代码即可。
2. 修正Azure AD配置
你需要先在Azure门户确认应用注册配置:
- 若使用ROPC流,需要将应用注册为公开客户端,不需要配置回调地址
- 给应用授予
Dynamics 365 Business Central的委派权限,并且由租户管理员完成权限同意 - 你用于认证的账号不能启用多因素认证(MFA),ROPC流不支持MFA账号,若必须用MFA账号请改用客户端凭据流
3. 修正请求地址与域名
- 将你代码中的authority域名从旧的
login.windows.net替换为微软当前正式使用的login.microsoftonline.com,格式为https://login.microsoftonline.com/<你的租户ID> - 你当前的serviceUrl只到Company路径,需要补充具体的实体集名称,例如要查询客户列表修改为:
https://api.businesscentral.dynamics.com/v2.0/<ID>/Sandbox/ODataV4/Company('My%20Company')/Customers
内容的提问来源于stack exchange,提问作者DOS
相关产品推荐
相关产品推荐

