从基于 OkHttp 的应用访问 WooCommerce Rest API 时出现问题
Issue while accessing WooCommerce Rest API from OkHttp based app
我想构建一个 android 客户端,该客户端可以使用 WooCommerce Api 提供的 Rest Api 与基于 WooCommerce 的网站进行交互
这是我的 android 代码。我正在使用 OkHttp 库进行网络连接。
public class MainActivity extends AppCompatActivity {
OkHttpClient client;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String cred = Credentials.basic("ck_...","cs_...");
OkHttpClient client = new OkHttpClient
.Builder()
.build();
Request req = new Request
.Builder()
.addHeader("Authorization",cred)
.url("http://10.0.2.2:8080/woocom/wp-json/wc/v2/products")
.build();
client.newCall(req).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("api resp", "onFailure: ");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("Api resp", "onResponse: "+response.body().string());
}
});
}
}
这是运行应用
后的错误日志
com.example.android.woocommerceapiintegration D/Api resp: onResponse: {"code":"woocommerce_rest_cannot_view","message":"Sorry, you cannot list resources.","data":{"status":401}}
我在这里做错了什么。我试用了 WooCommerce 提供的 NodeJS 客户端,效果很好。
此外,我无法根据 docs
中给出的命令通过 curl 访问其余部分 api
谁能告诉我我做错了什么?
更新:选择的答案是生产环境需要做的,技术上是正确的。如果你想在开发服务器上避免 OAuth 的麻烦,我已经单独回答了。
401 代码表示您的连接存在授权问题。具体来说,您的问题是由您通过 HTTP 连接使用 BasicAuth 引起的。
WooCommerce REST API Documentation 表示 BasicAuth 仅支持 HTTPS 连接,并且 HTTP 连接必须使用 OAuth 1.0a "one-Legged" 身份验证才能 "ensure" 您的凭据不会被攻击者拦截.
请务必注意,即使使用 OAuth 1.0a,HTTP 连接也永远不会真正安全,强烈建议将您的应用切换到安全的 HTTPS 连接。
同时,为了让您的代码正常工作,您必须为您的 Android 应用实施 OAuth 1.0a 身份验证方法。
您可以找到 Android here. The GitHub Page has an excellent guide with step-by-step instructions 的 OAuth 1.0a 实施的完整说明和完整项目示例,以了解如何使用上面链接的库。只需确保在使用提供的代码时确保考虑到您正在使用 OKHttp 的事实。幸运的是,作者已经很好地注释了说明中的代码,并记下了使用 OkHttp 之类的东西时要进行的更改。
你可以使用 Retrofit and simply write an Interceptor which takes care of the 'nitty-gritty' part as detailed in the documentation here.
您也可以按照 WooCommerce Documentation here 中详述的分步指南生成您的 OAuth 签名,最后生成 encodedUrl,然后将其传递给您的 http 客户端。此过程涉及:(有关每个部分的详细规范,请参阅文档)
- 收集请求方法和URL
- 收集所有
oauth_*
参数并使用百分比编码和正确排序将它们编码为单个字符串。例如(取自 WooCommerce 文档):
oauth_consumer_key=abc123&oauth_signature_method=HMAC-SHA1
- 通过连接 1 和 2 的值来创建签名的基本字符串。例如:(再次来自 Docs):
GET&http%3A%2F%2Fwww.example.com%2Fwp-json%2Fwc%2Fv2%2Forders&oauth_consumer_key%3Dabc123%26oauth_signature_method%3DHMAC-SHA1
- 最终使用HMAC-SHA1(也支持HMAC-SHA256)生成签名。
就我个人而言,我会推荐第一种或第二种方法。 "No need to reinvent the wheel".
编辑:
您可以查看 this question,其中讨论了如何在本地开发环境中使用 OkHttp 使用自签名证书。
感谢 akseli 回答我 question.I 也给了你赏金,感谢你增加了我的知识。尽管如此,我还是找到了解决此问题的简单方法。
我担心的是,在开发过程中,我们通常没有基于 https 的服务器,因此必须经历繁琐的基于 OAuth 的过程,无论如何生产都不会使用该过程,因为我们可能会使用的服务器将启用https。
因此,要在 http 开发服务器上使用基本身份验证,您需要转到 [your wordpress directory]/wp-content/woocommerce/includes/api
。找出 class-wc-rest-authentication.php
。此 class 处理 api 身份验证。找到如下所示的身份验证功能
public function authenticate( $user_id ) {
// Do not authenticate twice and check if is a request to our endpoint in the WP REST API.
if ( ! empty( $user_id ) || ! $this->is_request_to_rest_api() ) {
return $user_id;
}
if ( is_ssl() ) {
return $this->perform_basic_authentication();
}
return $this->perform_oauth_authentication();
}
注释掉条件is_ssl并简单地return$this->perform_basic_authentication(),这样在任何情况下,都会执行基本身份验证。
注意:这是一个 hack,只是为了避免在开发环境中进行 OAuth 身份验证的麻烦,在生产环境中完全不推荐。
我想构建一个 android 客户端,该客户端可以使用 WooCommerce Api 提供的 Rest Api 与基于 WooCommerce 的网站进行交互
这是我的 android 代码。我正在使用 OkHttp 库进行网络连接。
public class MainActivity extends AppCompatActivity {
OkHttpClient client;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String cred = Credentials.basic("ck_...","cs_...");
OkHttpClient client = new OkHttpClient
.Builder()
.build();
Request req = new Request
.Builder()
.addHeader("Authorization",cred)
.url("http://10.0.2.2:8080/woocom/wp-json/wc/v2/products")
.build();
client.newCall(req).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("api resp", "onFailure: ");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("Api resp", "onResponse: "+response.body().string());
}
});
}
}
这是运行应用
后的错误日志com.example.android.woocommerceapiintegration D/Api resp: onResponse: {"code":"woocommerce_rest_cannot_view","message":"Sorry, you cannot list resources.","data":{"status":401}}
我在这里做错了什么。我试用了 WooCommerce 提供的 NodeJS 客户端,效果很好。
此外,我无法根据 docs
中给出的命令通过 curl 访问其余部分 api谁能告诉我我做错了什么?
更新:选择的答案是生产环境需要做的,技术上是正确的。如果你想在开发服务器上避免 OAuth 的麻烦,我已经单独回答了。
401 代码表示您的连接存在授权问题。具体来说,您的问题是由您通过 HTTP 连接使用 BasicAuth 引起的。
WooCommerce REST API Documentation 表示 BasicAuth 仅支持 HTTPS 连接,并且 HTTP 连接必须使用 OAuth 1.0a "one-Legged" 身份验证才能 "ensure" 您的凭据不会被攻击者拦截. 请务必注意,即使使用 OAuth 1.0a,HTTP 连接也永远不会真正安全,强烈建议将您的应用切换到安全的 HTTPS 连接。
同时,为了让您的代码正常工作,您必须为您的 Android 应用实施 OAuth 1.0a 身份验证方法。
您可以找到 Android here. The GitHub Page has an excellent guide with step-by-step instructions 的 OAuth 1.0a 实施的完整说明和完整项目示例,以了解如何使用上面链接的库。只需确保在使用提供的代码时确保考虑到您正在使用 OKHttp 的事实。幸运的是,作者已经很好地注释了说明中的代码,并记下了使用 OkHttp 之类的东西时要进行的更改。
你可以使用 Retrofit and simply write an Interceptor which takes care of the 'nitty-gritty' part as detailed in the documentation here.
您也可以按照 WooCommerce Documentation here 中详述的分步指南生成您的 OAuth 签名,最后生成 encodedUrl,然后将其传递给您的 http 客户端。此过程涉及:(有关每个部分的详细规范,请参阅文档)
- 收集请求方法和URL
- 收集所有
oauth_*
参数并使用百分比编码和正确排序将它们编码为单个字符串。例如(取自 WooCommerce 文档):oauth_consumer_key=abc123&oauth_signature_method=HMAC-SHA1
- 通过连接 1 和 2 的值来创建签名的基本字符串。例如:(再次来自 Docs):
GET&http%3A%2F%2Fwww.example.com%2Fwp-json%2Fwc%2Fv2%2Forders&oauth_consumer_key%3Dabc123%26oauth_signature_method%3DHMAC-SHA1
- 最终使用HMAC-SHA1(也支持HMAC-SHA256)生成签名。
就我个人而言,我会推荐第一种或第二种方法。 "No need to reinvent the wheel".
编辑: 您可以查看 this question,其中讨论了如何在本地开发环境中使用 OkHttp 使用自签名证书。
感谢 akseli 回答我 question.I 也给了你赏金,感谢你增加了我的知识。尽管如此,我还是找到了解决此问题的简单方法。
我担心的是,在开发过程中,我们通常没有基于 https 的服务器,因此必须经历繁琐的基于 OAuth 的过程,无论如何生产都不会使用该过程,因为我们可能会使用的服务器将启用https。
因此,要在 http 开发服务器上使用基本身份验证,您需要转到 [your wordpress directory]/wp-content/woocommerce/includes/api
。找出 class-wc-rest-authentication.php
。此 class 处理 api 身份验证。找到如下所示的身份验证功能
public function authenticate( $user_id ) {
// Do not authenticate twice and check if is a request to our endpoint in the WP REST API.
if ( ! empty( $user_id ) || ! $this->is_request_to_rest_api() ) {
return $user_id;
}
if ( is_ssl() ) {
return $this->perform_basic_authentication();
}
return $this->perform_oauth_authentication();
}
注释掉条件is_ssl并简单地return$this->perform_basic_authentication(),这样在任何情况下,都会执行基本身份验证。
注意:这是一个 hack,只是为了避免在开发环境中进行 OAuth 身份验证的麻烦,在生产环境中完全不推荐。