【发布时间】:2018-04-20 14:12:25
【问题描述】:
问候我的开发人员,
我已经 3 天没有成功连接到 Cosmos DB 了。
我使用改造作为我的 REST 客户端和 GsonConverterFactory 用于序列化/反序列化。
当前状态是我从 Cosmos DB REST API 获得 HTTP:400(错误请求)。我尝试采用来自this SO answer 的身份验证标头生成
这是我的代码(此单元测试可在您的开发环境中运行。请参阅本文底部的gradle.build 行来运行它):
@RunWith(AndroidJUnit4.class)
@MediumTest
public class AzureDbConnectionTests {
public static final int COSMOS_PORT_NUM = 443;
public static final String COSMOS_DB_URL = "https://mazedb.documents.azure.com";
public static final String CONNECTION_STR =
COSMOS_DB_URL + ":" + COSMOS_PORT_NUM;
public static final String PRIMARY_KEY =
"<Private Key>";
// Entity to serialize into Cosmos DB
public static class Building {
public Building() {}
private String mName;
private String mAddress;
private String id;
}
public interface FirstAzureService {
@POST("/dbs/mazedb/colls/buildings/docs")
Call<Building> addDocument(
@Header("authorization") String authorization,
@Header("x-ms-date") String date,
@Body Building building);
}
@Test
public void serverConnectionTest() throws Exception {
String headerDate = getDateString();
Building building = new Building();
building.mName = "UUID";
building.id = UUID.randomUUID().toString();
Retrofit retrofit = new Retrofit.Builder().baseUrl(CONNECTION_STR)
.addConverterFactory(GsonConverterFactory.create()).build();
FirstAzureService azureService = retrofit.create(FirstAzureService.class);
Call<Building> buildingCall = azureService.addDocument(
generateAuthHeader("post", "docs", "dbs/mazedb/colls/buildings",
headerDate, PRIMARY_KEY), headerDate, building);
Response<Building> response = buildingCall.execute();
Log.d("AzureDbConnectionTest", "HTTP status code: " + response.code());
Log.d("AzureDbConnectionTest", "HTTP message: " + response.message());
Log.d("AzureDbConnectionTest", headerDate);
assertTrue(response.isSuccessful());
}
private String generateAuthHeader(String verb, String resourceType, String resourceId, String headerDate, String masterKeyBase64) throws Exception
{
//Decode the master key, and setup the MAC object for signing.
byte[] masterKeyBytes = Base64.decode(PRIMARY_KEY, Base64.NO_WRAP);
Mac mac = Mac.getInstance("HMACSHA256");
mac.init(new SecretKeySpec(masterKeyBytes, "HMACSHA256"));
//Build the unsigned auth string.
String stringToSign = verb.toLowerCase() + "\n"
+ resourceType.toLowerCase() + "\n"
+ resourceId.toLowerCase() + "\n"
+ headerDate.toLowerCase() + "\n"
+ "\n";
//Sign and encode the auth string.
String signature = Base64.encodeToString(
mac.doFinal(stringToSign.toLowerCase().getBytes("UTF8")), Base64.NO_WRAP);
//Generate the auth header.
String authHeader =
URLEncoder.encode("type=master&ver=1.0&sig=" + signature, "UTF8");
return authHeader;
}
@NonNull
public static String getDateString() {
SimpleDateFormat formatter =
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
return formatter.format(new Date()).toLowerCase();
}
}
API 是 SQL API。 Azure 仪表板上显示的数据库数据: db structure
我还尝试为 android 找到一些可用的 Cosmos DB 客户端,以节省处理身份验证和其他操作的时间。但只能找到这个:https://github.com/Azure/Azure.Android。这正是我正在寻找的,但它仍在开发中并且缺少 MongoDB API(我想使用 MongoDB API 来更容易地切换,如果它来了)。
非常感谢您的帮助!我已经厌倦了。
附: Azure Cosmos DB 的 HTTP 状态代码列表可以在 on official website 找到。从那里代码400的原因是:
- 请求正文中的 JSON、SQL 或 JavaScript 无效。
- 此外,当资源的所需属性不存在或未在资源的 POST 或 PUT 正文中设置时,也可以返回 400。
- 当 GET 操作的一致性级别被帐户的一组更强的一致性覆盖时,也会返回 400。
- 当需要 x-ms-documentdb-partitionkey 的请求不包含它时,也会返回 400。
我认为最有可能是错误的 JSON,但在另一个单元测试中对同一对象进行序列化后,我发现它没问题: {"id":"cceb3f5d-8d9c-44cd-85ee-599cd2f58783","mName":"UUID"}
最诚挚的问候,格雷格。
build.gradle 运行它:
dependencies {
androidTestCompile "junit:junit:4.12"
androidTestCompile "com.android.support:support-annotations:25.3.1"
androidTestCompile "com.android.support.test:runner:0.5"
androidTestCompile "com.android.support.test:rules:0.5"
androidTestCompile "com.google.code.gson:gson:2.8.2"
androidTestCompile "com.squareup.retrofit2:retrofit:2.4.0"
androidTestCompile "com.squareup.retrofit2:converter-gson:2.4.0"
}
【问题讨论】:
-
您必须立即更改您的帐户密钥!
-
@GauravMantri 我编辑了它,但我认为他拒绝了编辑
-
我可能会错过编辑。这些键并不重要。 DB 仅用于启动项目。当然,我稍后会更改密钥。谢谢。
-
@GregoryStein 人们可以更改报价并开始向您发送垃圾邮件以向您收费。
-
@Elfocrash 仅供参考,即使您编辑了某人的密钥(应该这样做),任何有足够代表的人都可以阅读编辑历史并查看密钥,这就是为什么在意外发布合法时更改密钥至关重要的原因, 当前键。
标签: android rest azure retrofit2 azure-cosmosdb