首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > Java Web开发 >

HttpClient模拟登录新浪微博!

2012-12-15 
HttpClient模拟登录新浪微博求助!!!!!!!!!!以下是参考网上找到的代码修改后的源码,可是登录不成功,望指教

HttpClient模拟登录新浪微博求助!!!!!!!!!!
以下是参考网上找到的代码修改后的源码,可是登录不成功,望指教或探讨!!!
QQ:940154985


package cn.vangdo.search;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

public class SinaLogin {

private final static HttpClient client = new DefaultHttpClient();   
/**
 * 抓取网页
 *
 * @param url
 * @throws IOException
 */
static String get(String url) throws IOException {
HttpGet get = new HttpGet(url);
HttpResponse response = client.execute(get);
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
String result = dump(entity);
get.abort();
return result;
}   
/**
 * 执行登录过程
 *
 * @param user
 * @param pwd
 * @param debug
 * @throws IOException
 */
static void login(String user, String pwd) throws IOException {
HttpPost post = new HttpPost(
"http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.17)");
post.setHeader("User-Agent",
"Mozilla/5.0 (X11; Linux i686; rv:5.0) Gecko/20100101 Firefox/5.0");
post.setHeader("Referer", "http://weibo.com/");
post.setHeader("Content-Type", "application/x-www-form-urlencoded");   // 登录表单的信息
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("entry", "account"));
qparams.add(new BasicNameValuePair("gateway", "1"));
qparams.add(new BasicNameValuePair("from", ""));
qparams.add(new BasicNameValuePair("savestate", "0"));
qparams.add(new BasicNameValuePair("useticket", "0"));
qparams.add(new BasicNameValuePair("ssosimplelogin", "1"));
qparams.add(new BasicNameValuePair("service", "account"));
qparams.add(new BasicNameValuePair("servertime", "1323790225"));
qparams.add(new BasicNameValuePair("nonce", "FUD0TL"));
// servertime=1309164392
// nonce=PJZCHM
qparams.add(new BasicNameValuePair("pwencode", "wsse"));
qparams.add(new BasicNameValuePair("encoding", "UTF-8")); 
qparams.add(new BasicNameValuePair(
"url",
"http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack")); 
qparams.add(new BasicNameValuePair("returntype", "IFRAME"));
qparams.add(new BasicNameValuePair("setdomain", "1"));
qparams.add(new BasicNameValuePair("username", user));
qparams.add(new BasicNameValuePair("password", pwd));


UrlEncodedFormEntity params = new UrlEncodedFormEntity(qparams, "UTF-8");
post.setEntity(params);   // Execute the request
HttpResponse response = client.execute(post);
post.abort();
// 新浪微博登录没有301,302之类的跳转;而是返回200,然后用javascript实现的跳转
// int statusCode = response.getStatusLine().getStatusCode();
// if ((statusCode == HttpStatus.SC_MOVED_PERMANENTLY)
// || (statusCode == HttpStatus.SC_MOVED_TEMPORARILY)
// || (statusCode == HttpStatus.SC_SEE_OTHER)
// || (statusCode == HttpStatus.SC_TEMPORARY_REDIRECT)) {
// // 此处重定向处理 此处还未验证
// String newUri = response.getLastHeader("Location").getValue();
// get(newUri);
// }   // Get hold of the response entity
HttpEntity entity = response.getEntity();

// 取出跳转的url
// location.replace("http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&ticket=ST-MTkxODMxOTI0Nw==-1309224549-xd-263902F174B27BAB9699691BA866EFF2&retcode=0");
String location = getRedirectLocation(dump(entity));
System.out.println("entity:"+dump(entity));
System.out.println("location:"+location);
//get(location);
}

private static String getRedirectLocation(String content) {
String regex = "location\\.replace\\("(.*?)"\\)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(content);
String location = null;
if (matcher.find()) {
location = matcher.group(1);
}   return location;
}   

/**
 * 打印页面
 *
 * @param entity
 * @throws IOException
 */
private static String dump(HttpEntity entity) throws IOException {
//System.out.println("content11:"+entity.getContent());
BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent(),"utf-8"));

File fl = new File("D:\\1.txt");//写入到本地的文件名称
FileOutputStream fos=new FileOutputStream(fl);

int data = br.read();

while(data!=-1) {   
fos.write(data);   
data=br.read();   
}   
fos.close();


System.out.println("content:"+data);
//return IOUtils.toString(br);
return "aa";



public static void main(String[] args) throws IOException {
//System.out.println("begin999"); 
login("username", "password");
String result = get("http://t.sina.com.cn/pub/tags");
System.out.println(result);
}
}

[最优解释]
我在研究爬虫程序时,也有需要爬去新浪微博的模块。同样遇到的类似的问题。以下为我目前登录的方式。结果是能够登录成功和爬取内容的。


HttpClient client = new HttpClient();

client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);

PostMethod post = new PostMethod("http://login.sina.com.cn/sso/login.php?

client=ssologin.js(v1.3.16)");

String data = getServerTime();

String nonce = makeNonce(6);

NameValuePair[] nvps = new NameValuePair[] {


new NameValuePair("entry", "weibo"),
new NameValuePair("gateway", "1"),
new NameValuePair("from", ""),
new NameValuePair("savestate", "7"),
new NameValuePair("useticket", "1"),
new NameValuePair("ssosimplelogin", "1"),
new NameValuePair("vsnf", "1"),
new NameValuePair("vsnval", ""),
new NameValuePair("su", encodeAccount(微博用户名)),
new NameValuePair("service", "miniblog"),
new NameValuePair("servertime", data),
new NameValuePair("nonce", nonce),
new NameValuePair("pwencode", "wsse"),
new NameValuePair("sp", new SinaSSOEncoder().encode(微博密码, data, nonce)),
new NameValuePair("encoding", "UTF-8"),
new NameValuePair("returntype", "META"),
new NameValuePair(
"url",
"http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack") };

post.setRequestBody(nvps);

client.executeMethod(post);

// 此处是测试用的。获取到【正在登录页面跳转的url,此url为实际登录获取cookie的url】
String url = post.getResponseBodyAsString().substring(post.getResponseBodyAsString().indexOf("http://weibo.com/ajaxlogin.php?"),post.getResponseBodyAsString().indexOf("code=0")+6);

// 获取到实际url进行连接
GetMethod getMethod = new GetMethod(url);

client.executeMethod(getMethod);

GetMethod weiBoMethod = new GetMethod("http://需要登录才能访问的微博地址");

// 实际访问微博
status = client.executeMethod(getMethod);



此处status返回是200.我做了页面解析,以前爬取的微博页面一直是登录页面,经过上面的步骤,此处为登录后的微博页面。

与君共勉。

我调查时的参考资料:
http://blog.sina.com.cn/s/blog_4f52c70d0100uz51.html
http://www.byywee.com/page/M0/S609/609772.html
[其他解释]
参考以下做了点修改

http://flychen.com/article/sign-in-java-and-perl-sina-microblogging.html
[其他解释]
提示用新浪API的就别说了
[其他解释]
代码太多了,把日志贴出来看看!

简单看了代码,思路没问题.
[其他解释]
首先感谢 xiachedan !

打印日志如下:

content:-1
Exception in thread "main" java.lang.IllegalStateException: Content has been consumed
at org.apache.http.entity.BasicHttpEntity.getContent(BasicHttpEntity.java:84)
at org.apache.http.conn.BasicManagedEntity.getContent(BasicManagedEntity.java:87)
at cn.vangdo.search.SinaLogin.dump(SinaLogin.java:119)
at cn.vangdo.search.SinaLogin.login(SinaLogin.java:96)
at cn.vangdo.search.SinaLogin.main(SinaLogin.java:141)



1.txt文件内容如下:

<html>
<head>
<title>sina iframe login</title>
<meta http-equiv="Content-Type" content="text/html; charset=GBK" />
</head>
<body>
<script>
if(1) document.domain = "sina.com.cn";
({"retcode":"2092","reason":"\u62b1\u6b49\uff01\u767b\u5f55\u5931\u8d25\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5"});;
</script>
</body>
</html>
[其他解释]
不成功的错误至少得看下啊

很多无法登录一主要原因是目标网站分析出了来源是机器登录
把可能泄露登录方式的信息给剔除或配合网站希望
比如from参数之类的
------其他解决方案--------------------


1.txt中的\u62b1\u6b49\uff01\u767b\u5f55\u5931\u8d25\uff0c\u8bf7\u7a0d\u5019\u518d\u8bd5解析为:抱歉!登录失败,请稍候再试
[其他解释]
java.lang.IllegalStateException: Content has been consumed

你这个错误是 getContent被再次调用了(dump之前可能已经获取过,再次调用就会报错)


post.setHeader("User-Agent",
"Mozilla/5.0 (X11; Linux i686; rv:5.0) Gecko/20100101 Firefox/5.0");
还有User-Agent head field的信息可能导致登录被拒绝,以前碰到过



[其他解释]
getContent在整个代码中只用了一次阿
[其他解释]
楼主可以试试badboy这个软件,很简单的一个软件可以自动分析出登陆过程,然后在用java实现出登陆过程就可以了,模拟登陆我一直这么做的.
[其他解释]
登录时username和password需要经过加密?
[其他解释]
http://topic.csdn.net/u/20111214/13/c36fd65a-6b86-4897-9b0b-9a53a8368031.html
我写得一个新浪客户端,是调用新浪提供的SDK的。希望对你有所帮助。
[其他解释]
用新浪的sdk,我也做过了,但是想实现查询微博的功能,需要新浪审批,太麻烦,所以想用别的方式来做。
[其他解释]

引用:
getContent在整个代码中只用了一次阿

String location = getRedirectLocation(dump(entity));
System.out.println("entity:"+dump(entity));

这里不就已经两次了
[其他解释]
dracularking
谢谢!去掉System.out.println("entity:"+dump(entity));之后,不报错了!

但是输出结果为:
location:null
HTTP/1.1 200 OK


1.txt中打印出的内容是微博登录页面,看来还是没有登录成功啊!


是不是用户名和密码得加密之后再放到程序里边?用什么样的加密方式呢?
[其他解释]
引用:
dracularking
谢谢!去掉System.out.println("entity:"+dump(entity));之后,不报错了!

但是输出结果为:
location:null
HTTP/1.1 200 OK


1.txt中打印出的内容是微博登录页面,看来还是没有登录成功啊!


是不是用户名和密码得加密之后再放到程序里边?用什么样的加密方式呢?

需不需要加密也只有抓包了能看出多少是多少,或者直接找到点什么现成资料
[其他解释]
qparams.add(new BasicNameValuePair("returntype", "IFRAME"));
qparams.add(new BasicNameValuePair("returntype", "META"));

这两个有什么区别?用IFRAME时不报错,但是打印出location:null,且1.txt内容为登录页面;
用META时报错:
Exception in thread "main" java.net.SocketException: socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:130)
at org.apache.http.impl.io.SocketInputBuffer.fillBuffer(SocketInputBuffer.java:127)
at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:161)
at org.apache.http.impl.conn.LoggingSessionInputBuffer.read(LoggingSessionInputBuffer.java:68)
at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:159)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:138)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)


at java.io.BufferedReader.read(Unknown Source)
at cn.vangdo.search.Sian.dump(Sian.java:129)
at cn.vangdo.search.Sian.login(Sian.java:96)
at cn.vangdo.search.Sian.main(Sian.java:142)
[其他解释]
最直接还是抓包,根据实际成功登录情况来模拟
需要加哪些head field,分别是什么值,加密方式等等
你上面returntype是不是应该加META值呢,服务端没法获取相关信息了
[其他解释]
= 128 << (24 - r % 32);
A[((r + 64 >> 9) << 4) + 15] = r;
int[] B = new int[80];
int z = 1732584193;
int y = -271733879;
int v = -1732584194;
int u = 271733878;
int s = -1009589776;
for (int o = 0; o < A.length; o += 16) {
int q = z;
int p = y;
int n = v;
int m = u;
int k = s;
for (int l = 0; l < 80; l++) {
if (l < 16) {
B[l] = A[o + l];
} else {
B[l] = d(B[l - 3] ^ B[l - 8] ^ B[l - 14] ^ B[l - 16], 1);
}
int C = e(e(d(z, 5), a(l, y, v, u)), e(e(s, B[l]), c(l)));
s = u;
u = v;
v = d(y, 30);
y = z;
z = C;
}
z = e(z, q);
y = e(y, p);
v = e(v, n);
u = e(u, m);
s = e(s, k);
}
return new int[] { z, y, v, u, s };
}

private int a(int k, int j, int m, int l) {
if (k < 20) {
return (j & m) 
[其他解释]
上面的回复中,最后一行写错了。。抱歉。
应该是status = client.executeMethod(weiBoMethod);

另附上:新浪加密算法的代码


private static String encodeAccount(String account) {
return Base64.encode(URLEncoder.encode(account).getBytes());
}

private static String makeNonce(int len) {
String x = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String str = "";
for (int i = 0; i < len; i++) {
str += x.charAt((int) (Math.ceil(Math.random() * 1000000) % x
.length()));
}
return str;
}

private static String getServerTime() {
long servertime = new Date().getTime() / 1000;
return String.valueOf(servertime);


public class SinaSSOEncoder {
private boolean i = false;
private int g = 8;

public SinaSSOEncoder() {

}

public String encode(String psw, String servertime, String nonce) {
String password;
password = hex_sha1("" + hex_sha1(hex_sha1(psw)) + servertime + nonce);
return password;
}

private String hex_sha1(String j) {


return h(b(f(j, j.length() * g), j.length() * g));
}

private String h(int[] l) {
String k = i ? "0123456789ABCDEF" : "0123456789abcdef";
String m = "";
for (int j = 0; j < l.length * 4; j++) {
m += k.charAt((l[j >> 2] >> ((3 - j % 4) * 8 + 4)) & 15) + ""
+ k.charAt((l[j >> 2] >> ((3 - j % 4) * 8)) & 15);
}
return m;
}

private int[] b(int[] A, int r) {
A[r >> 5] 
[其他解释]
 (j & l) 
[其他解释]
 ((~j) & l);
}
;
if (k < 40) {
return j ^ m ^ l;
}
;
if (k < 60) {
return (j & m) 
[其他解释]
 (l & 65535);
}

private int d(int j, int k) {
return (j << k) 
[其他解释]
 (m & l);
}
;
return j ^ m ^ l;
}

private int c(int j) {
return (j < 20) ? 1518500249 : (j < 40) ? 1859775393
: (j < 60) ? -1894007588 : -899497514;
}

private int e(int j, int m) {
int l = (j & 65535) + (m & 65535);
int k = (j >> 16) + (m >> 16) + (l >> 16);
return (k << 16) 
[其他解释]
= (m.charAt(k / g) & j) << (24 - k % 32);
}
return l;
}

}




[其他解释]
 (j >>> (32 - k));
}

private int[] f(String m, int r) {
int[] l;
int j = (1 << this.g) - 1;
int len = ((r + 64 >> 9) << 4) + 15;
int k;
for (k = 0; k < m.length() * g; k += g) {
len = k >> 5 > len ? k >> 5 : len;
}
l = new int[len + 1];
for (k = 0; k < l.length; k++) {
l[k] = 0;
}
for (k = 0; k < m.length() * g; k += g) {
l[k >> 5] 
[其他解释]
TO:afengsakura
非常感谢!!!

不过你试过现在登录能成功吗?我用你的方式登录不成功呢?虽然status返回是200,但是打印出内容看还是登录页面呢???

现在最新的ssologin.js(v1.3.17)而不是你的ssologin.js(v1.3.16)了!



QQ请教一下?我的QQ:940154985
[其他解释]
 Content has been consumed是内容已经注销了。你再去拿数据是拿不到的

[其他解释]
有点繁琐啊
[其他解释]
很好!搞定!
[其他解释]
我也很想知道19楼大牛是怎么知道加密算法的!!!
[其他解释]
关键就是新浪加密算法啊。
19楼(afengsakura) 我挺好奇你怎么知道算法的。
牛逼破解分析 Or 新浪老员工 Or 认识新浪开发人员 ?

热点排行