`
逆风的香1314
  • 浏览: 1391954 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

OpenAPI的使用代码-登录CSDN

阅读更多
原文地址:
http://www.java2000.net/p7715
http://blog.csdn.net/java2000_net/archive/2008/07/30/2736659.aspx
此文的版权归JAVA世纪网(www.java2000.net)和CSDN(www.csdn.net)所有,转载请保留此声明、代码注释和原始链接


CSDN在很早以前就提供了登录CSDN的OpenAPI,原始地址如下:http://passport.csdn.net/WebService/UserLoginService.asmx

原理分析
系统提供了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提交请求,就如同你用浏览器直接访问一样。


附件:
系统用到的postPage的源代码
  /**
   * 提交数据到指定的地址
   *
   * @param urlTo 指定提交的地址
   * @param host 主机名称
   * @param cookies cookies的数据
   * @param data 提交的数据
   * @return 返回提交的结果数组,[0] 为返回的cookie 数据,[1]为返回的内容本体数据
   */
  private static String[] postPage(String urlTo, String host, String cookies, String data) {
    try {
      URL url = new URL(urlTo);
      HttpURLConnection con = (HttpURLConnection) url.openConnection();
      con.setDoOutput(true); // POST方式
      con.setRequestMethod("POST");
      con.addRequestProperty("Host", host);
      con.addRequestProperty("Content-Type", "application/soap+xml; charset=utf-8");
      if (cookies != null) {
        con.addRequestProperty("Cookie", cookies);
      }
      byte[] bs = data.getBytes("UTF-8");
      con.addRequestProperty("Content-Length", Integer.toString(bs.length));
      OutputStream os = con.getOutputStream(); // 输出流,写数据
      os.write(bs);
      Map<String, List<String>> map = con.getHeaderFields();
      String[] rtn = new String[2];
      String cookie = "";
      if (map.get("Set-Cookie") != null)
        for (String v : map.get("Set-Cookie")) {
          cookie += v.substring(0, v.indexOf(";") + 1);
        }
      rtn[0] = cookie;
      BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream(),
          "UTF-8")); // 读取结果
      String line;
      StringBuilder b = new StringBuilder();
      while ((line = reader.readLine()) != null) {
        b.append(line);
      }
      reader.close();
      rtn[1] = b.toString();
      return rtn;
    } catch (Exception ex) {
      ex.printStackTrace();
      return null;
    }
  }












<script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script>
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics