Chinaunix
标题:
OpenAPI的使用代码-登录CSDN
[打印本页]
作者:
杨竹青
时间:
2008-07-30 12:58
标题:
OpenAPI的使用代码-登录CSDN
原理分析
系统提供了2个方法
UserLogin
UserPreLogin
我们要使用这个服务,必须经过2个步骤。
1 预登录,获取一些验证信息(ClientKey)以及验证码图片
2 显示验证码图片,并让用户输入用户名和密码
3 提交数据,包括ClientKey,用户名和密码,以及验证码
4 拿到结果,最重要的就是 cookie的信息(ErrorInfo)
我们依然使用
URLConnection直接进行数据处理的方法.
先看预登录的部分。
看看协议
POST /WebService/UserLoginService.asmx HTTP/1.1
Host: passport.csdn.net
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<UserPreLogin xmlns="http://passport.csdn.net/">
<RobotName>string</RobotName>
</UserPreLogin>
</soap12:Body>
</soap12:Envelope>
实现的代码
/**
* 预登录CSDN系统
*
* @author 赵学庆,www.java2000.net
* @param username 预登录的用户名
* @return 结果数组.[0]:验证码的字符串, [1] Client的字符串 ,[2] Cookie数据
*/
public static String[] preLogin(String username) {
StringBuilder b = new StringBuilder();
try {
b.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
b
.append("<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n");
b.append(" <soap12:Body>\n");
b.append(" <UserPreLogin xmlns=\"http://passport.csdn.net/\">\n");
b.append(" <RobotName>" + username + "</RobotName>\n");
b.append(" </UserPreLogin>\n");
b.append(" </soap12:Body>\n");
b.append("</soap12:Envelope>\n");
String[] strs = postPage("http://passport.csdn.net/WebService/UserLoginService.asmx",
"passport.csdn.net", null, b.toString());
String textXml = strs[1];
SAXBuilder builder = new SAXBuilder();
Document doc = null;
Reader in = new StringReader(textXml);
doc = builder.build(in);
Element root = doc.getRootElement();
List ls = root.getChildren();// 注意此处取出的是root节点下面的一层的Element集合
Element body = (Element) ls.get(0);
Element response = (Element) body.getChildren().get(0);
List content = response.getChildren();
Element result = (Element) content.get(0);
Element result2 = (Element) content.get(1);
String[] rtn = new String[3];
if ("UserPreLoginResult".equals(result.getName())) {
rtn[0] = result.getText();
}
if ("ClientKey".equals(result2.getName())) {
rtn[1] = result2.getText();
}
rtn[2] = strs[0];
return rtn;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
调用的登录表单代码
<form method="post">
<table>
<tr>
<td>CSDN用户名</td>
<td><input type="text" name="username" /></td>
</tr>
<tr>
<td>CSDN密码</td>
<td><input type="password" name="password" /></td>
</tr>
<tr>
<td>图形验证码</td>
<td><input type="text" size="6" name="code" /><br>
<img id="vc" src="getCSDNImage.jsp" /></td>
</tr>
<tr>
<th>保存密码</th>
<td><input type="checkbox" name="savePassword" value="true" id="savePassword" tabindex="-1" /></td>
</tr>
<tr>
<td colspan="2">
<button type="submit">登陆</button>
</td>
</tr>
</table>
</form>
其中的显示验证码的部分是关键
String[] rtn = OpenAPI.preLogin("java2000_net_test");
session.setAttribute("CSDN_ClientKey",rtn[1]);
session.setAttribute("CSDN_COOKIE",rtn[2]);
OutputStream os = response.getOutputStream();
os.write( org.apache.commons.codec.binary.Base64.decodeBase64(rtn[0].getBytes()));
里面讲返回的信息记录到了session里面,以备下次调用时使用
提示:返回的验证码图片数据是Base64编码后的,需要先解码才能使用。
到目前为止,预登录完成
下面我们进入第二步,登录
先看登录的协议
POST /WebService/UserLoginService.asmx HTTP/1.1
Host: passport.csdn.net
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<UserLogin xmlns="http://passport.csdn.net/">
<LoginName>string</LoginName>
<Password>string</Password>
<VerifyCode>string</VerifyCode>
<ClientKey>string</ClientKey>
</UserLogin>
</soap12:Body>
</soap12:Envelope>
参数有4个,登录的用户名,密码,认证码和ClientKey
登录返回的XML协议
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelopexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<UserLoginResponse xmlns="http://passport.csdn.net/">
<UserLoginResult>boolean</UserLoginResult>
<ErrorInfo>string</ErrorInfo>
<WarningInfo>string</WarningInfo>
</UserLoginResponse>
</soap12:Body>
</soap12:Envelope>
其中的
UserLoginResult为登录结果
ErrorInfo 为登录失败的错误信息
WarningInfo 我没用,估计是不是被暴力破解的那个警告啊
实现的代码
/**
* 登录CSDN系统
*
* @author 赵学庆,www.java2000.net
* @param username 登录的用户名
* @param password 密码
* @param verifyCode 校验码
* @param clientkey 预登录的clientKey
* @param cookie 预登录拿到的cookie
* @return 登录结果,[0] 登录结果,'true'成功, [1] 错误信息,[2] 登录后的cookie数据
*/
public static String[] login(String username, String password, String verifyCode,
String clientkey, String cookie) {
StringBuilder b = new StringBuilder();
try {
b.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
b
.append("<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n");
b.append(" <soap12:Body>\n");
b.append(" <UserLogin xmlns=\"http://passport.csdn.net/\">\n");
b.append(" <LoginName>" + username + "</LoginName>\n");
b.append(" <Password>" + password + "</Password>\n");
b.append(" <VerifyCode>" + verifyCode + "</VerifyCode>\n");
b.append(" <ClientKey>" + clientkey + "</ClientKey>\n");
b.append(" </UserLogin>\n");
b.append(" </soap12:Body>\n");
b.append(" </soap12:Envelope>\n");
String[] strs = postPage("http://passport.csdn.net/WebService/UserLoginService.asmx",
"passport.csdn.net", cookie, b.toString());
String textXml = strs[1];
SAXBuilder builder = new SAXBuilder();
Document doc = null;
Reader in = new StringReader(textXml);
doc = builder.build(in);
Element root = doc.getRootElement();
List ls = root.getChildren();// 注意此处取出的是root节点下面的一层的Element集合
Element body = (Element) ls.get(0);
Element response = (Element) body.getChildren().get(0);
List content = response.getChildren();
Element result = (Element) content.get(0);
Element result2 = (Element) content.get(1);
String[] rtn = new String[3];
if ("UserLoginResult".equals(result.getName())) {
rtn[0] = result.getText();
}
if ("ErrorInfo".equals(result2.getName())) {
rtn[1] = result2.getText();
}
rtn[2] = strs[0];
return rtn;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
下面看登录的程序
String username = request.getParameter("username");
String password = request.getParameter("password");
String code = request.getParameter("code");
String clientKey = (String) session.getAttribute("CSDN_ClientKey");
String cookies = (String) session.getAttribute("CSDN_COOKIE");
String[] rtn = OpenAPI.login(username, password, code, clientKey, cookies);
if ("true".equals(rtn[0])) {
out.println("登陆成功!");
// 其它的处理代码
return;
} else {
out.println("登陆失败:" + rtn[1]);
}
总结:
这个OpenAPI设计的还是挺好的,我们拿到ClientKey 和 Cookie之后,就可以在其它的请求里面把他们放在cookie里,直接向CSDN提交请求,就如同你用浏览器直接访问一样。
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2