Java 中的两条腿 OAuth2 示例?
我有一个提供 REST 服务 + OAuth2 的 示例 web.py 应用。在Python中,客户端应用程序会经历生成OAuth2消费者、请求、签名等过程。类似这样的(伪代码参考,不完整):
import json
import time
import oauth2
import urllib2
# Set up the POST variables
method = 'POST'
url = 'https://localhost/service/rest'
parameters = {
'username' : username,
'password' : password
}
# Generate our Consumer object
consumer = oauth2.Consumer( key = KEY, secret = SECRET )
# Add additional parameters required by OAuth
parameters['oauth_version'] = "1.0"
parameters['oauth_nonce'] = oauth2.generate_nonce()
parameters['oauth_timestamp'] = int(time.time())
parameters['oauth_consumer_key'] = consumer.key
# Generate and sign the request
oauth = oauth2.Request( method = method, url = url, parameters = parameters )
signature_method = oauth2.SignatureMethod_HMAC_SHA1()
oauth.sign_request( signature_method, consumer, None )
# Shoot it off to the webserver
req = urllib2.Request( BASE_URL, oauth.to_postdata() )
result = urllib2.urlopen( req ).read()
json_result = json.loads( result )
print json_result
TADA!它就像冠军一样工作。我正在尝试在 Java 下做同样的事情,特别是在 Android 上,但此时我会采取任何措施。我见过的所有示例都集中在使用三足身份验证的公共 OAuth2 API 上,或者集中在 Web 服务的服务器端配置上。
有人可以可怜我并给我指出一个使用 BasicHttpContext、DefaultHttpClient 和朋友的同样简单的 Java 示例吗?
稍后编辑
回答自己的问题可能被认为是不好的形式,但以下是如何执行我的要求。事实证明,两条腿的oauth确实是OAuth v1.0的功能,所以半废弃的oauth.signpost库可以轻松做到。我尝试使用最近维护的 joauth 库,但找不到任何关于如何执行我想要的操作的好示例。该代码实际上分布在我的代码中的三个或四个不同的 java 文件中,但我在这个伪代码示例中将所有这些都放在一起。
import ...
import oauth.signpost.OAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
public class RestClient {
private OAuthConsumer oauth_consumer = null;
private DefaultHttpClient http_client;
private static final String consumer_key = "something";
private static final String consumer_secret = "something_else";
public RestClient( Context context ) {
// Instantiate our custom http client with our trusted key
this.http_client = new DefaultHttpClient();
// Instantiate an oauth_consumer
this.oauth_consumer = new CommonsHttpOAuthConsumer( consumer_key, consumer_secret );
}
public POST( String url, Map params ) {
// Initialize our post request
HttpPost httppost = new HttpPost( url );
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Content-type", "application/x-www-form-urlencoded");
// This iterates through the parameters and stores them for use
List<NameValuePair> name_value_pairs = new ArrayList<NameValuePair>(2);
Iterator iter = params.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry pairs = (Map.Entry)iter.next();
name_value_pairs.add(
new BasicNameValuePair( (String)pairs.getKey(), (String)pairs.getValue() )
);
}
try {
// Put our parameters in our Post
httppost.setEntity( new UrlEncodedFormEntity( name_value_pairs ) );
// sign our request
this.oauth_consumer.sign( httppost );
// Yoiks, and away!
HttpResponse response = http_client.execute( httppost );
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
JSONObject json = new JSONObject( convertStreamToString(instream) );
// Closing the input stream will trigger connection release
instream.close();
return json;
} catch ( aBunchOfShit e) {
e.printStackTrace();
}
}
return null;
}
}
当您在后端验证签名时,请务必包含您在请求中传递的所有参数。我坐在那里看着“无效签名。预期签名基字符串 POST&...”错误一个小时,直到我弄清楚如何设置 System.setProperty("debug","1");并在Java端看到了原始的基本字符串。目前这已经足够好了,但我仍然想看看它在维护的库下如何工作。
I've got an example web.py app supplying REST services + OAuth2. In Python, a client app goes through the process of generating an OAuth2 consumer, request, signing it, etc. something like this (pseudo code reference, not complete):
import json
import time
import oauth2
import urllib2
# Set up the POST variables
method = 'POST'
url = 'https://localhost/service/rest'
parameters = {
'username' : username,
'password' : password
}
# Generate our Consumer object
consumer = oauth2.Consumer( key = KEY, secret = SECRET )
# Add additional parameters required by OAuth
parameters['oauth_version'] = "1.0"
parameters['oauth_nonce'] = oauth2.generate_nonce()
parameters['oauth_timestamp'] = int(time.time())
parameters['oauth_consumer_key'] = consumer.key
# Generate and sign the request
oauth = oauth2.Request( method = method, url = url, parameters = parameters )
signature_method = oauth2.SignatureMethod_HMAC_SHA1()
oauth.sign_request( signature_method, consumer, None )
# Shoot it off to the webserver
req = urllib2.Request( BASE_URL, oauth.to_postdata() )
result = urllib2.urlopen( req ).read()
json_result = json.loads( result )
print json_result
TADA! It works like a champ. I'm trying to do the same thing under Java, well specifically on Android, but I'll take anything at this point. All the examples I've seen are focused on public OAuth2 APIs using three-legged auth or are focused on server side configurations for web-services.
Can someone take pity on me and point me to an equally simple example in Java using BasicHttpContext, DefaultHttpClient and friends?
EDITED LATER
It's probably considered bad form to answer your own questions, but here is how to do what I was asking. It turns out that two-legged oauth is really OAuth v1.0 functionality, so the semi-abandoned oauth.signpost library can do it easily. I tried to use the more recently maintained joauth library, but couldn't find any good examples of how to do just the bits I wanted. This code is actually spread around in three or four different java files in my code, but I did it all together for this pseudo code example.
import ...
import oauth.signpost.OAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
public class RestClient {
private OAuthConsumer oauth_consumer = null;
private DefaultHttpClient http_client;
private static final String consumer_key = "something";
private static final String consumer_secret = "something_else";
public RestClient( Context context ) {
// Instantiate our custom http client with our trusted key
this.http_client = new DefaultHttpClient();
// Instantiate an oauth_consumer
this.oauth_consumer = new CommonsHttpOAuthConsumer( consumer_key, consumer_secret );
}
public POST( String url, Map params ) {
// Initialize our post request
HttpPost httppost = new HttpPost( url );
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Content-type", "application/x-www-form-urlencoded");
// This iterates through the parameters and stores them for use
List<NameValuePair> name_value_pairs = new ArrayList<NameValuePair>(2);
Iterator iter = params.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry pairs = (Map.Entry)iter.next();
name_value_pairs.add(
new BasicNameValuePair( (String)pairs.getKey(), (String)pairs.getValue() )
);
}
try {
// Put our parameters in our Post
httppost.setEntity( new UrlEncodedFormEntity( name_value_pairs ) );
// sign our request
this.oauth_consumer.sign( httppost );
// Yoiks, and away!
HttpResponse response = http_client.execute( httppost );
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
JSONObject json = new JSONObject( convertStreamToString(instream) );
// Closing the input stream will trigger connection release
instream.close();
return json;
} catch ( aBunchOfShit e) {
e.printStackTrace();
}
}
return null;
}
}
When you verify your signature on the backend, be sure to include all the parameters you passed in the request. I sat looking at the "Invalid signature. Expected signature base string POST&..." error for an hour until I figured out how to set System.setProperty("debug","1"); and saw the original base string on the Java side. This works good enough for now, but I'd still like to see how it works under a maintained library.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
既然您提到了 joauth,我就编写了一个文档来允许使用 JOAuth 进行 OAuth 1 授权。
我希望这对你有帮助。
Since you've mentioned about joauth, I have written a documentation to allow OAuth 1 authorization using JOAuth.
I hope this helps you.