Android中调用SharePoint REST API列表项?Graph令牌致401错误求解
你的问题核心在于Graph API的访问令牌和SharePoint传统REST API的令牌受众不匹配,直接复用Graph的令牌自然会返回401未授权。下面是具体的解决步骤和代码调整方案:
1. 为什么会出现401?
Graph API的访问令牌受众(aud声明)是https://graph.microsoft.com,而SharePoint的/_api/web/...这类传统REST API要求令牌的受众是你的SharePoint站点根域(比如https://mysharepoint.sharepoint.com)或者具体站点URL。两者的令牌不能通用,必须针对SharePoint资源单独请求令牌。
2. 用MSAL请求SharePoint专属令牌
你需要修改MSAL的令牌请求逻辑,指定SharePoint的资源范围,而非Graph的范围:
- 针对租户内所有SharePoint站点,范围用
https://<你的租户域名>.sharepoint.com/.default - 针对特定站点,范围用
https://<你的租户域名>.sharepoint.com/sites/MySite/.default
MSAL获取SharePoint令牌的示例代码
// 替换为你的SharePoint资源域名 String SHAREPOINT_SCOPE = "https://mysharepoint.sharepoint.com/.default"; PublicClientApplication pca = PublicClientApplication.create(getContext(), YOUR_CLIENT_ID); List<String> scopes = Collections.singletonList(SHAREPOINT_SCOPE); pca.acquireToken(getActivity(), scopes, new AuthenticationCallback() { @Override public void onSuccess(IAuthenticationResult authResult) { // 拿到针对SharePoint的有效令牌 String sharePointToken = authResult.getAccessToken(); // 触发SharePoint API调用 callSharePointRestApi(sharePointToken); } @Override public void onError(MsalException exception) { Log.e(TAG, "获取SharePoint令牌失败: " + exception.getMessage()); } @Override public void onCancel() { Log.d(TAG, "用户取消令牌请求"); } });
3. 调整Volley请求的细节
除了替换令牌,还要注意你的SharePoint API URL有个小问题:getbytitle ('Announcements')里的空格会导致URL解析错误,需要改成getbytitle('Announcements')。
调整后的Volley请求代码
// 修正后的SharePoint REST API URL String SHAREPOINT_API_URL = "https://mysharepoint.sharepoint.com/sites/MySite/_api/web/lists/getbytitle('Announcements')/Items"; JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, SHAREPOINT_API_URL, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { Log.d(TAG, "SharePoint API响应: " + response.toString()); // 这里处理返回数据并更新UI } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.d(TAG, "SharePoint API请求错误: " + error.toString()); } }) { @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> headers = new HashMap<>(); // 使用SharePoint专属令牌 headers.put("Authorization", "Bearer " + sharePointToken); // 添加请求头确保返回简洁的JSON格式 headers.put("Accept", "application/json;odata=nometadata"); return headers; } }; // 设置重试策略并加入请求队列 request.setRetryPolicy(new DefaultRetryPolicy( 3000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); queue.add(request);
4. 额外注意事项
- 权限配置:在Azure AD应用注册中,必须添加SharePoint相关权限(比如
Sites.Read.All、Sites.ReadWrite.All),且需要管理员完成权限同意(租户级应用场景)。 - 令牌刷新:SharePoint令牌和Graph令牌一样有有效期,MSAL会自动处理令牌刷新,后续可以调用
acquireTokenSilent获取刷新后的令牌。
内容的提问来源于stack exchange,提问作者007
相关产品推荐
相关产品推荐

