- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我一直在尝试学习如何使用 oAuth 1.0a 向服务器验证 Android 应用程序的身份(我知道它已经过时了,但这是我被迫使用的。),并且我一直在关注有关如何将应用程序连接到 oAuth1.0a 的教程 here
但是,在编写了他们建议的 Activity 之后,我遇到了如下错误:
oauth.signpost.exception.OAuthCommunicationException: Communication with the service provider failed: No peer certificate
at oauth.signpost.AbstractOAuthProvider.retrieveToken(AbstractOAuthProvider.java:218)
at oauth.signpost.AbstractOAuthProvider.retrieveRequestToken(AbstractOAuthProvider.java:74)
at com.company.companyone.account.PrepareRequestTokenActivity$OAuthRequestTokenTask.doInBackground(PrepareRequestTokenActivity.java:141)
at com.company.companyone.account.PrepareRequestTokenActivity$OAuthRequestTokenTask.doInBackground(PrepareRequestTokenActivity.java:122)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856)
引起:javax.net.ssl.SSLPeerUnverifiedException:没有对等证书
我写的 Activity 如下:
public class PrepareRequestTokenActivity extends Activity {
private CommonsHttpOAuthConsumer consumer;
private CommonsHttpOAuthProvider provider;
private final static String TAG = "PrepareRequestTokenActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prepare_request_token);
try {
System.setProperty("debug", "true");
consumer = new CommonsHttpOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
provider = new CommonsHttpOAuthProvider(
Constants.REQUEST_URL,
Constants.ACCESS_URL,
Constants.AUTHORIZE_URL);
provider.setOAuth10a(true);
} catch (Exception e) {
Log.d(TAG, "Error intializing consumer and provider", e);
e.printStackTrace();
}
Log.i(TAG, "Starting task to retrieve request token.");
new OAuthRequestTokenTask(this,consumer,provider).execute();
}
@Override
protected void onResume(){
super.onResume();
//need to get the preferences to store response tokens later.
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
final Uri uri = getIntent().getData();
//make sure that the callback worked correctly
if(uri != null && uri.getScheme().equals(Constants.OAUTH_CALLBACK_SCHEME)){
Log.i(TAG, "Got Callback : uri = " +uri);
Log.i(TAG, "Attempting to Retrieve Access Token");
new RetrieveAccessTokenTask(this,consumer,provider,prefs).execute(uri);
//done
finish();
}else{
Log.d(TAG, "Fatal Error: oAuth Callback malformed.");
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_prepare_request_token, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class OAuthRequestTokenTask extends AsyncTask<String, Void, String>{
private CommonsHttpOAuthConsumer reqConsumer;
private CommonsHttpOAuthProvider reqProvider;
private Context context;
public OAuthRequestTokenTask(PrepareRequestTokenActivity prepareRequestTokenActivity, CommonsHttpOAuthConsumer reqConsumer, CommonsHttpOAuthProvider reqProvider){
this.context = prepareRequestTokenActivity.getApplicationContext();
this.reqConsumer = reqConsumer;
this.reqProvider = reqProvider;
}
@Override
protected String doInBackground(String... strings) {
try {
Log.i(TAG, "Retrieving request token from Magento servers");
final String url = reqProvider.retrieveRequestToken(reqConsumer, Constants.OAUTH_CALLBACK_URL);
Log.i(TAG, "Popping a browser with the authorize URL : " + url);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_FROM_BACKGROUND);
context.startActivity(intent);
} catch (Exception e) {
Log.e(TAG, "Error during OAUth retrieve request token", e);
e.printStackTrace();
}
return null;
}
}
private class RetrieveAccessTokenTask extends AsyncTask<Uri, Void, Void> {
private Context context;
private CommonsHttpOAuthConsumer consumer;
private CommonsHttpOAuthProvider provider;
private SharedPreferences prefs;
//collect the instance variables for the Access Token request
public RetrieveAccessTokenTask(PrepareRequestTokenActivity prepareRequestTokenActivity, CommonsHttpOAuthConsumer consumer, CommonsHttpOAuthProvider provider, SharedPreferences prefs) {
this.context = prepareRequestTokenActivity.getApplicationContext();
this.consumer = consumer;
this.provider = provider;
this.prefs = prefs;
}
//called by .execute()
//takes Verifier Token and uses it to retrieve the Access Token by validating this instance of the app.
@Override
protected Void doInBackground(Uri... params) {
final Uri oauth_uri = params[0];
final String verifier = oauth_uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
try{
//set the provider to do it's ish.
provider.retrieveAccessToken(consumer,verifier);
//save the token in the shared preferences so that we can use it in our request methods.
//MAKE SURE YOU LEAVE THIS AS COMMIT. We want this to persist in memory, and apply doesn't guarantee that the token will remain if the app closes immediately.
final SharedPreferences.Editor edit = prefs.edit();
edit.putString(OAuth.OAUTH_TOKEN, consumer.getToken());
edit.putString(OAuth.OAUTH_TOKEN_SECRET, consumer.getTokenSecret());
edit.commit();
String token = prefs.getString(OAuth.OAUTH_TOKEN,"");
String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET,"");
consumer.setTokenWithSecret(token,secret);
Toast.makeText(context, "Token Success! += "+ token, Toast.LENGTH_LONG);
//kick it back to the mainactivity.
context.startActivity(new Intent(context, MainActivity.class));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
我不确定我遇到的错误是由于运行 Magento 网络服务器的 VM 的错误 SSL 证书引起的,还是错误出在我的代码中。如果有帮助,SSL 证书是自签名的,以便可以通过专用网络对其进行测试。
//oAuth Constants
public static final String REQUEST_URL="https://myhost/oauth/initiate";
public static final String ACCESS_URL="https://myhost/oauth/token";
public static final String AUTHORIZE_URL="https://myhost/oauth/authorize ";
这是抛出错误的行。
final String url = reqProvider.retrieveRequestToken(reqConsumer, Constants.OAUTH_CALLBACK_URL);
我将错误追溯到 CommonsHttpOAuthProvider.sendRequest() 方法。它在以下位置中断:
HttpResponse response = httpClient.execute((HttpUriRequest) request.unwrap());
在执行 request.unwrap() 调用之前。
TL;DR:我是不是做错了什么,Android 是不是不喜欢自签名 SSL 证书?
最佳答案
简短回答:是的,SSL 证书导致了问题。以下自签名证书和乱序证书的解决方案。
注意:我很确定这不会影响安全性,但我也不确定 SSL 证书的顺序是否非常重要。因此,请对此持保留态度。我绝对计划在实时环境启动并运行后将其删除,因此我不建议将此代码保留在您的应用程序中,除非您的环境完全受控并且您将连接到的所有主机都是已知的。
第 1 步:乱序证书。需要定义一个自定义 TrustManager 来为您处理错误的证书。(我在某处在线找到了对此解决方案的引用,但我现在找不到链接)。
/**
* Created by Nevuroth on 1/19/15.
*/
public class CustomX509TrustManager implements X509TrustManager{
private X509TrustManager defaultManager = null;
/**
* Custom constructor for the x509 trust manager. This workaround won't take away from security, but it will drop and accept the self signed cert for our test server at the
* end of the cert chain, as well as allowing
*
* @param keyStore
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
*/
public CustomX509TrustManager(KeyStore keyStore) throws NoSuchAlgorithmException, KeyStoreException{
super();
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init(keyStore);
TrustManager[] trustManagers = factory.getTrustManagers();
if(trustManagers.length ==0){
throw new NoSuchAlgorithmException("Failed to find Default trust managers");
}
this.defaultManager = (X509TrustManager) trustManagers[0];
}
//we just want the standard functionality for x509
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
defaultManager.checkClientTrusted(x509Certificates, s);
}
/**
* Here's where the magic happens, we're going to be compensating for out of order certificates in the X509 header
* as well as compensating for self-signed certificates (kind of), by passing the certificate before it in the chain
* to the chekc servertrusted method
* This won't compensate for purely self-signed certs.... but you can do so by adding it to the accepted issuers method.
* @param x509Certificates
* @param s
* @throws CertificateException
*/
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
//Clean the certificates and make sure they are in the proper order.
int chainln = x509Certificates.length;
if(x509Certificates.length > 1){
//Clean the chains by matching issuer and subject fields until we can't continue
int index;
boolean foundNext;
for(index=0; index < x509Certificates.length; ++index){
foundNext = false;
for(int nextIndex = index + 1; nextIndex < x509Certificates.length; ++nextIndex){
//look for the next certificate in the chain.
if(x509Certificates[index].getIssuerDN().equals(x509Certificates[nextIndex].getSubjectDN())){
foundNext = true;
//exchange certificates so that 0 through index+1 are in proper order.
if(nextIndex != index+1){
X509Certificate tempCert = x509Certificates[nextIndex];
x509Certificates[nextIndex] = x509Certificates[index+1];
x509Certificates[index+1] = tempCert;
}
break;
}
}
if(!foundNext){
break;
}
}
//if the cert is self signed and if it is expired, if so we drop it and pass the rest to checkServerTrusted, hoping we may have a similar bu unexpired trusted root.
chainln = index +1;
X509Certificate lastCert = x509Certificates[chainln - 1];
Date now = new Date();
if(lastCert.getSubjectDN().equals(lastCert.getIssuerDN()) && now.after(lastCert.getNotAfter())){
--chainln;
}
}
defaultManager.checkServerTrusted(x509Certificates, s);
}
//you can add an accepted issuer
@Override
public X509Certificate[] getAcceptedIssuers() {
return this.defaultManager.getAcceptedIssuers();
}
}
第 2 步:创建一个自定义 SSLSocketFactory 来实现我们的新信任管理器。
/**
* Created by Nevuroth on 1/19/15.
*/
public class CustomSSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException, KeyStoreException {
super(truststore);
TrustManager tm = new CustomX509TrustManager(truststore);
sslContext.init(null, new TrustManager[]{tm}, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
return sslContext.getSocketFactory().createSocket(socket, host, port,autoClose);
}
@Override
public Socket createSocket() throws IOException{
return sslContext.getSocketFactory().createSocket();
}
}
第 3 步:实现一个新的 HTTPClient,它使用我们刚刚创建的自定义 SSLSocketFactory。在为 https 连接定义 HTTPClient 时使用它。
public HttpClient getNewHttpClient(){
try{
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
//sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(),80));
registry.register(new Scheme("https", sf,443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params,registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
e.printStackTrace();
//if we get an error here then we need to return something or a fatal network error will occur.
return new DefaultHttpClient();
}
}
关于Android:oauth.signpost.exception.OAuthCommunicationException:与服务提供商的通信失败:没有对等证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27992740/
我正在使用 Clarity Signposts并需要它的状态(无论是打开还是关闭)。我正在使用 *clrIfOpen 结构指令并为其分配了 isOpen 变量。 isOpen 最初为 false,但在
我正在尝试按照以下示例在我的 android 应用程序中实现 tumblr 登录:https://github.com/jansanz/TumblrOAuthDemo . 我可以获得请求 token
我一直在尝试学习如何使用 oAuth 1.0a 向服务器验证 Android 应用程序的身份(我知道它已经过时了,但这是我被迫使用的。),并且我一直在关注有关如何将应用程序连接到 oAuth1.0a
我有一个自定义的 Xcode 13.2.1 (13C100) Instrument,我最近添加了 os-signpost-point-schema .我注意到事件标有连字符/破折号而不是 ⓢ。查看我的
我不知道pinCode是什么,也不知道如何获取它?!我找到了以下代码,正如前面提到的,我们可以从 CallBack 中获取它,如何获取?如果还有其他方法请告诉我.. 代码 OAuthConsumer
我正在使用 Retrofit 2 在 Android 应用程序中发出 http 请求。我与之交谈的服务器需要 OAuth 1.0 授权。我使用此处的 okhttp-signpost 来处理 OAuth
我将在我的 Android 应用程序中访问 linkedin 个人资料。我使用了下面的代码,它在安卓设备上运行良好,但在模拟器上崩溃了。不知道哪里出了问题。我的代码如下。 配置.java public
你好,我正在尝试将 Twitter 与 OAuth 结合使用,但我收到此异常 授权失败(服务器回复 401)。如果消费者 key 不正确或签名不匹配,就会发生这种情况。 我正在使用这个示例 http:
我阅读了很多关于路标的内容,然后回到 Twitter4J,在不需要 OAuth 的情况下我用它创建了我的 Twitter 应用程序。 我现在很困惑是应该使用 signpost 还是 Twitter4J
我正在尝试使用 OAuth 身份验证来连接到各种服务。对于这大部分,这是有效的(使用 twitter/photobucket 进行测试),但使用 Evernote,我收到了 400 响应代码。 这里出
我正在通过 SocialLib 项目使用 Twitter 集成。但事情是不断得到 java.lang.NoClassDefFoundError: oauth.signpost.commonshttp.
所以我正在使用 Signpost Java 的 OAuth 库。我在使用 Apache Commons HTTP 库时遇到了一些问题。看看下面的代码: URL url = new URL("http:
使用路标 1.2: String authUrl = provider.retrieveRequestToken( consumer, callbackUrl ); Netflix API 响应:
我目前正在使用 OAuth-Signpost Java 库对从客户端发送到实现 OAuth 身份验证的服务器的请求进行签名。发出 GET 请求(使用 HttpURLConnection)时一切正常:请
尝试使用路标 oauth 库从 android 客户端调用。我生成了新的 APIv2 key ,但似乎没有什么不同。我得到的错误看起来像: {"error":{"text":"Signature wa
我是一名优秀的程序员,十分优秀!