OMG,到底在尋找什么..................
          (構(gòu)造一個完美的J2EE系統(tǒng)所需要的完整知識體系)
          posts - 198,  comments - 37,  trackbacks - 0

          原貼地址:http://www.wujianrong.com/archives/2006/12/e.html

          版本0.1

          前段時間開發(fā)聯(lián)通彩e接口,期間遇到很多問題,在朋友的幫助和自己的摸索中總算完成了接口的開發(fā)。在sp聯(lián)盟論壇上也見到許多同行各種各樣的問題,因此將開發(fā)細節(jié)整理成文,希望能給與我當初一樣 困擾的人以幫助。第一次接觸彩e,感覺有點無從下手,接口指南幾百頁之多,我在開發(fā)的時候不知道聯(lián)通提供測試的接入平臺以供調(diào)試,而是對著接口規(guī)范編寫代碼,然后模擬接口規(guī)則生成數(shù)據(jù),這些都是在單元測試中完成 的,到接入uni-wise測試環(huán)境時,問題多多。

          目錄

          概述
          1. SSO接口

          ??? 1.1. 傳輸安全
          ??? 1.2. 生成請求票根
          ??? 1.3. 解析響應(yīng)票根

          2. 預(yù)定接口

          ??? 2.1. 發(fā)起預(yù)定請求
          ??? 2.2. 解析uni-wise預(yù)定請求
          ??? 2.3. 驗證請求
          ??? 2.4. 響應(yīng)預(yù)定請求

          3. 預(yù)定取消接口

          ??? 3.1. 發(fā)起取消請求
          ??? 3.2. 解析uni-wise取消請求
          ??? 3.3. 驗證請求
          ??? 3.4. 響應(yīng)請求

          4. web push接口

          ??? 4.1. 提交push







          概述





          本文以java語言為例,講述彩e接口開發(fā)的點滴。參考的接口指南為《中國聯(lián)通增值業(yè)務(wù)綜合管理及接入平臺SP接口規(guī)范v1.2》, 文中代碼均經(jīng)過測試,且與uni-wise平臺能正常運行。彩e與sp接口包括:sso接口、預(yù)定接口、取消接口、彩e push接口,取 消push接口,查詢push接口、wap push接口。文中除了wap push接口,其余的將會一一介紹。 彩e接口的開發(fā)其實就是sp與聯(lián)通uni-wise平臺之間的通信,uni-wise平臺是以web方式工作,因此與sp的交互大部分通 過http+xml協(xié)議傳輸。 筆者在開發(fā)的過程中也曾用C#寫過彩e的部分接口代碼,如有此需求,我也將整理成文。







          第?1?章?SSO接口





          SSO 是 Single sign on的縮寫,即單點登錄,彩e接口中實現(xiàn)的功能是,用戶在uni-wise平臺或sp平臺只需登錄一次,即可 訪問相關(guān)資源。通過cookies機制實現(xiàn)。






          1.1.?傳輸安全





          出于安全考慮,網(wǎng)絡(luò)的傳輸中經(jīng)常對傳輸數(shù)據(jù)做加密和編碼處理,彩e接口開發(fā)中的一個關(guān)鍵點也是對加密解密的代碼編寫。 其中涉及以下幾種:


          1、md5加密,該加密算法是單向加密,即加密的數(shù)據(jù)不能再通過解密還原。相關(guān)類包含在java.security.MessageDigest包中。


          2、3-DES加密,該加密算法是可逆的,解密方可以通過與加密方約定的密鑰匙進行解密。相關(guān)類包含在javax.crypto.*包中。


          3、base64編碼,是用于傳輸8bit字節(jié)代碼最常用的編碼方式。相關(guān)類在sun.misc.BASE64Decoder 和sun.misc.BASE64Encoder 中。


          4、URLEncoder編碼,是一種字符編碼,保證被傳送的參數(shù)由遵循規(guī)范的文本組成。相關(guān)類在java.net.URLEncoder包中。







          1.2.?生成請求票根





          當用戶從SP平臺向uni-wise發(fā)起登錄請求時,SP平臺需要生成一個合法的票根,以http協(xié)議傳輸給uni-wise平臺。 生成請求票根的規(guī)則是:SPTicketRequestValue = URLEncoding{UNICODE(SPCode +“$”)+ Base64 [Encrypt (UNICODE(Seed + “$”)+ Digest)]}


          1、生成Seed: returnUrl + "$" + timeStamp;returnUrl為登錄成功后接收uni-wise的響應(yīng)票根鏈接。timeStamp為生成的 時間戳。



          例?1.1.?TimeStamp實現(xiàn)代碼


          public String getTimeStamp()
          {
          Calendar cal=Calendar.getInstance();
          SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
          String timeStamp=formatter.format(cal.getTime());
          return timeStamp;
          }


          2、生成Digest :Base64{Hash[UNICODE(SPCode +"$"+ Seed + "$" + SPKey)]},其中Hash算法采用md5



          例?1.2.?Digest的實現(xiàn)代碼


          public String getDigest(String strSrc)
          {
          //String strSrc = spCode + "___FCKpd___1quot; + getSeed() + "___FCKpd___1quot; + spKey;
          BASE64Encoder base64en = new BASE64Encoder();
          String digest="";
          try
          {
          byte[] srcMD5 = md5Encrypt(strSrc);
          digest = base64en.encode(srcMD5); (1)
          }
          catch(Exception e){
          e.printStackTrace();
          }
          return digest;
          }

          private byte[] md5Encrypt(String strSrc)
          {
          byte[] returnByte = null;
          try
          {
          MessageDigest md5 = MessageDigest.getInstance("MD5"); (2)
          returnByte = md5.digest(strSrc.getBytes("GBK"));
          }
          catch(Exception e)
          {
          e.printStackTrace();
          }
          return returnByte;
          }














          (1)

          用base64編碼


          (2)

          指定加密方式為md5




          3、生成密鑰匙,用聯(lián)通提供的key,進行md5加密。



          例?1.3.?得到3-DES的密鑰匙


          private byte[] getEnKey(String spKey)
          {
          byte[] desKey=null;
          try
          {
          byte[] desKey1 = md5Encrypt(spKey);
          desKey = new byte[24];
          int i = 0;
          while (i < desKey1.length && i < 24) {
          desKey[i] = desKey1[i];
          i++;
          }
          if (i < 24) { (1)
          desKey[i] = 0;
          i++;
          }
          }
          catch(Exception e){
          e.printStackTrace();
          }
          return desKey;
          }










          (1)

          根據(jù)接口規(guī)范,密鑰匙為24個字節(jié),md5加密出來的是16個字節(jié),因此后面補8個字節(jié)的0




          4、生成SPTicketRequestValue,URLEncoding{UNICODE(SPCode +“$”)+ Base64 [Encrypt (UNICODE(Seed + “$”)+ Digest)]}, Encrypt算法采用3-DES加密,用md5加密的key作為密鑰匙。



          例?1.4.?3-DES加密的實現(xiàn)代碼


          public String getSPTicketRequestValue()
          {
          String SPTicketRequestValue="";
          try{
          byte[] src = (getSeed() + "___FCKpd___3quot; + getDigest() ).getBytes("UTF-16LE");
          byte[] enKey = getEnKey(spKey);
          byte[] encryptedData = Encrypt(src,enKey); (1)
          String base64Encrypt = filter(base64en.encode(encryptedData)); (2)
          String requestValue=spCode + "___FCKpd___3quot; + base64Encrypt;
          SPTicketRequestValue=URLEncoder.encode(requestValue);
          }
          catch(Exception e){
          e.printStackTrace();
          }
          return SPTicketRequestValue;
          }

          public byte[] Encrypt(byte[] src,byte[] enKey)
          {
          byte[] encryptedData = null;
          try
          {
          DESedeKeySpec dks = new DESedeKeySpec(enKey); (3)
          SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede"); (4)
          SecretKey key = keyFactory.generateSecret(dks); (5)
          Cipher cipher = Cipher.getInstance("DESede"); (6)
          cipher.init(Cipher.ENCRYPT_MODE, key); (7)
          encryptedData = cipher.doFinal(src); (8)
          }
          catch(Exception e)
          {
          e.printStackTrace();
          }
          return encryptedData;
          }

          private String filter(String str)
          {
          String output = null;
          StringBuffer sb = new StringBuffer();
          for(int i = 0; i < str.length(); i++)
          {
          int asc = str.charAt(i);
          if(asc != 10 && asc != 13)
          sb.append(str.subSequence(i, i + 1));
          }
          output = new String(sb);
          return output;
          }






































          (1)

          調(diào)用3-DES的加密函數(shù)。


          (2)

          base64編碼3-DES的數(shù)據(jù)時,得到的字符串有換行符號,一定要去掉,否則uni-wise平臺解析票根不會成功, 提示“sp驗證失敗”。在開發(fā)的過程中,因為這個問題讓我束手無策,一個朋友告訴我可以問聯(lián)通要一段加密后 的文字,然后去和自己生成的字符串比較,這是個不錯的調(diào)試方法。我最后比較發(fā)現(xiàn)我生成的字符串唯一不同的 是多了換行。我用c#語言也寫了票根請求程序,沒有發(fā)現(xiàn)這個問題。


          (3)

          從原始密匙數(shù)據(jù)創(chuàng)建DESedeKeySpec對象。


          (4)

          創(chuàng)建一個密匙工廠,然后用它把DESKeySpec轉(zhuǎn)換成一個SecretKey對象。


          (5)

          根據(jù)密匙工廠,得到一個密鑰匙實例。


          (6)

          創(chuàng)建Cipher對象。


          (7)

          初始化Cipher對象(帶入密鑰匙)。


          (8)

          執(zhí)行加密操作。




          為方便調(diào)試給出一段加密后的字符串(用自己的代碼加密同樣的字符串后得到的結(jié)果和給出的結(jié)果進行比較)


          content = key = 1234;
          result = base64(3des(contentbyte,keybyte));
          result : "25Pxmw/+/qKg2arQpLdvqQ=="






          1.3.?解析響應(yīng)票根





          uni-wise平臺收到請求票根后會進行解析票根,然后用戶登錄后uni-wise又會將登錄信息放在響應(yīng)票根中,傳回給請求票根者。 (傳回的地址是請求票根中的”returnUrl“)。傳輸?shù)膮f(xié)議也是http+xml.


          1、UrlEncoding的解碼(筆者在測試中發(fā)現(xiàn)在uni-wise測試平臺首先需要對所得的票根響應(yīng)串進行urlEncoding解碼,這也是接口 遵照接口手冊進行的,但是在uni-wise正式平臺下得到的響應(yīng)票根已經(jīng)是對urlEncoding解碼的)。


          import java.net.URLDecoder;
          URLDecoder.decode(strEncoding);

          2、分割響應(yīng)票根,得到加密的字符串。分割很簡單,以"$"為分割符,得到"$"后面的字符串即可。


          3、對加密字符串進行base64解碼。


          import sun.misc.BASE64Decoder;
          BASE64Decoder base64Decode = new BASE64Decoder();
          base64Decode.decodeBuffer(strEnBase64);

          4、對base64解碼的值進行3-DES解密(密鑰匙等同于加密的密鑰匙)。


          public String deCrypt(byte[] debase64)
          {
          String strDe = null;
          Cipher cipher = null;
          try
          {
          cipher=Cipher.getInstance("DESede");
          byte[] key = getEnKey(spKey); (1)
          DESedeKeySpec dks = new DESedeKeySpec(key);
          SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
          SecretKey sKey = keyFactory.generateSecret(dks);
          cipher.init(Cipher.DECRYPT_MODE, sKey); (2)
          byte ciphertext[] = cipher.doFinal(debase64);
          strDe = new String(ciphertext,"UTF-16LE");
          }
          catch(Exception ex)
          {
          strDe = "";
          ex.printStackTrace();
          }
          return strDe;
          }













          (1)

          得到密鑰匙,具體實現(xiàn)請參考請求票根部分


          (2)

          加密、解密其實就是指定這個類型 Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE




          5、通過"$"分割解密的字符串,然后取得對應(yīng)的信息,如MDN,UserId等。如果SP需要記錄用戶信息,應(yīng)該在解析票根后 持久存儲。然后根據(jù)實際需要將用戶信息加入cookies.以實現(xiàn)SSO。








          第?2?章?預(yù)定接口









          2.1.?發(fā)起預(yù)定請求





          用戶可以從SP平臺和uni-wise平臺發(fā)起預(yù)定請求,當從SP發(fā)起預(yù)定請求時,SP平臺需要 構(gòu)建預(yù)定請求的數(shù)據(jù),以htpp協(xié)議傳輸給uni-wise.請求數(shù)據(jù)的構(gòu)建有兩種方式一種是 service方式,一種是product方式.根據(jù)實際情況構(gòu)建請求參數(shù)。 http://接入平臺的URL?SPCode=A&ServiceCode=B&ReturnURL=C (service方式) http://接入平臺的URL?SPCode=A&ProductCode=B&ReturnURL=C (product方式)







          2.2.?解析uni-wise預(yù)定請求





          所有的預(yù)定操作都是鏈接到uni-wise預(yù)定平臺,然后用戶在此發(fā)生預(yù)定關(guān)系,uni-wise構(gòu)建 預(yù)定信息通知SP平臺,根據(jù)SP的響應(yīng)結(jié)果,決定預(yù)定動作成功與否。uni-wise要將預(yù)定信息 通知SP,因此需要預(yù)先知道SP接收預(yù)定的鏈接,這是在申請彩e業(yè)務(wù)時完成。



          例?2.1.?解析預(yù)定請求


          InputStream subscriptionRequestStream = request.getInputStream();  (1)
          PraseXml(subscriptionRequestStream); (2)














          (1)

          uni-wise將預(yù)定信息以輸出流傳輸?shù)絊P平臺,SP用HttpServletRequest得到輸入流。


          (2)

          ParseXml為解析xml的函數(shù)。與解析普通的xml一樣,因此在此不再描述其實現(xiàn)方法。









          2.3.?驗證請求





          得到預(yù)定請求信息后,應(yīng)該對其數(shù)據(jù)進行驗證,根據(jù)驗證的結(jié)果返回相應(yīng)的信息給uni-wise平臺。


          if (mdn == null || mdn.trim().equals(""))
          {
          errorCode = "16842754";
          errorInfo = "cannot find MDN";
          }

          if ( spCode == null || spCode.trim().equals(""))
          {
          errorCode = "16973826";
          errorInfo = "cannot find SPCode";
          }

          if (productCode == null || productCode.trim().equals(""))
          {
          errorCode = "17104898";
          errorInfo = "cannot find ProductCode";
          }
          if (transactionID == null || transactionID.trim().equals(""))
          {
          errorCode = "17170434";
          errorInfo = "cannot find TransactionID";
          }






          2.4.?響應(yīng)預(yù)定請求





          SP接收到uni-wise預(yù)定請求信息后進行驗證核對,然后響應(yīng)請求,傳輸協(xié)議為http+xml。 uni-wise得到響應(yīng)后執(zhí)行預(yù)定動作,返回給用戶預(yù)定相關(guān)信息。SP處理請求結(jié)果有成功 和失敗兩種情況。



          例?2.2.?請求成功的響應(yīng)格式


          StringBuffer sb = new StringBuffer();
          sb.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
          sb.append("<U-MAX>\n");
          sb.append("<PreSubscriptionNotify>\n");
          sb.append("<MDN>" + getMdn() + "</MDN>\n");
          sb.append("<SPCode>" + getSpCode() + "</SPCode>\n");
          sb.append("<ProductCode>" + getProductCode() + "</ProductCode>\n");
          sb.append("<TransactionID>" + getTransactionID() + "</TransactionID>\n");
          sb.append("</PreSubscriptionNotify>\n");
          sb.append("</U-MAX>");
          String strResponse = new String(sb);




          例?2.3.?請求失敗的響應(yīng)格式


          StringBuffer sb = new StringBuffer();
          sb.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
          sb.append("<U-MAX>\n");
          sb.append("<ValidError>\n");
          sb.append("<ValidErrorCode>");
          sb.append(getErrorCode());
          sb.append("</ValidErrorCode>");
          sb.append("<ValidErrorInfo>");
          sb.append(getErrorInfo());
          sb.append("</ValidErrorInfo>");
          sb.append("</ValidError>\n");
          sb.append("</U-MAX>");
          String strResponse = new String(sb);








          第?3?章?預(yù)定取消接口









          3.1.?發(fā)起取消請求





          用戶可以從SP平臺和uni-wise平臺發(fā)起取消請求,當從SP發(fā)起取消請求時,SP平臺需要 構(gòu)建取消請求的數(shù)據(jù),以htpp協(xié)議傳輸給uni-wise.請求數(shù)據(jù)的構(gòu)建有兩種方式一種是 service方式,一種是product方式.規(guī)則同預(yù)定請求一致。







          3.2.?解析uni-wise取消請求





          所有的取消操作也是定向到uni-wise平臺,然后用戶在此執(zhí)行取消動作,uni-wise接收 到用戶取消動作后將取消信息通知SP平臺,根據(jù)SP的響應(yīng)結(jié)果,決定取消動作成功與否。 SP的取消接收鏈接,也是在申請彩e業(yè)務(wù)時完成。實現(xiàn)代碼與解析預(yù)定請求代碼一致,在此 不再重復(fù)。







          3.3.?驗證請求





          請參考預(yù)定請求章節(jié)的相應(yīng)內(nèi)容。







          3.4.?響應(yīng)請求






          例?3.1.?請求處理成功的響應(yīng)


          StringBuffer sb = new StringBuffer();
          sb.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
          sb.append("<U-MAX>\n");
          sb.append("<SubscriptionCancel>\n");
          sb.append("<MDN>" + getMdn() + "</MDN>\n");
          sb.append("<SPCode>" + getSpCode() + "</SPCode>\n");
          sb.append("<ProductCode>" + getProductCode() + "</ProductCode>\n");
          sb.append("<TransactionID>" + getTransactionID() + "</TransactionID>\n");
          sb.append("</SubscriptionCancel>\n");
          sb.append("</U-MAX>");
          String strResponse = new String(sb);



          例?3.2.?請求處理失敗的響應(yīng)


          StringBuffer sb = new StringBuffer();
          sb.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
          sb.append("<U-MAX>\n");
          sb.append("<ValidError>\n");
          sb.append("<ValidErrorCode>");
          sb.append(getErrorCode());
          sb.append("</ValidErrorCode>");
          sb.append("<ValidErrorInfo>");
          sb.append(getErrorInfo());
          sb.append("</ValidErrorInfo>");
          sb.append("</ValidError>\n");
          sb.append("</U-MAX>");
          String strResponse = new String(sb);








          第?4?章?web push接口





          發(fā)送彩e,先提交到uni-wise平臺的push接口,然后再由uni-wise push到IMAP平臺,如圖:




          圖?4.1.?







          4.1.?提交push





          SP 提交信息到 uni-wise Push接口的數(shù)據(jù)分包頭和包體,其中包體以MIME格式傳輸。


          1、構(gòu)建包頭: SP的企業(yè)代碼(不加密)+ SP的密鑰(加密)+付費代碼(加密)+條件類別(加密)+條件代碼(加密) +發(fā)送方式(加密)+[發(fā)送開始時間(加密)+截止時間(加密)]+ 計費手機號碼(加密)+ MIME包體 中的邊界字段Boundary(加密)


          import java.net.HttpURLConnection;
          import java.net.URL;

          private Url url = null;
          HttpURLConnection conn = null;

          //先建立URL長連接
          public void connectUrl(String strUrl)
          {
          try
          {
          url = new URL(strUrl);
          conn = (HttpURLConnection)url.openConnection();
          conn.setRequestMethod("post");
          }
          catch(Exception ex)
          {

          }
          }

          //設(shè)置包頭
          public void setHeader()
          {
          conn.setRequestProperty("SPCode", spCode);
          conn.setHeader("EncryptSPKey",enKey);
          conn.setHeader("FeeCode",enFeeCode );
          conn.setHeader("ConditionType",enConditionType);
          conn.setHeader("ConditionCode", enConditionCode);
          conn.setHeader("SendType", enSendType);
          conn.setHeader("StartTime", enStartTime);
          conn.setHeader("EndTime",enEndTime);
          conn.setHeader("ThirdPartyPayPhone",enThirdPartyPayPhone);
          conn.setHeader("Boundary", enBoundary);
          }

          包頭中除了spcode不用加密,其余的都遵行base64(3des(contentbyteplus,keybyte))加密方式。 加密的實現(xiàn)代碼和前面章節(jié)描述的一致。


          2、構(gòu)建包體


          MIME (Multipurpose Internet Mail Extensions,多目的Internet郵件擴展)是創(chuàng)建用于電子郵件交換, 網(wǎng)絡(luò)文檔,及企業(yè)網(wǎng)和Internet上的其他應(yīng)用程序中的文件格式的規(guī)范.



          例?4.1.?構(gòu)建MIME格式的包體


          private MimeMessage mime;
          //構(gòu)造MIME格式的包體
          private void setMimeMessage()
          {
          try
          {
          mime.setFrom(new InternetAddress(strFrom)); (1)
          mime.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(strTo)); (2)
          mime.setSubject(strSubject,"UTF-8"); (3)
          mime.setSentDate(new Date());
          mime.setContent(getMimeMultipart());
          }
          catch(Exception ex)
          {
          }
          }
          private MimeMultipart getMimeMultipart()
          {
          MimeMultipart mimeMultipart = new MimeMultipart();
          MimeBodyPart mimeBodyPart = new MimeBodyPart();
          try
          {
          mimeBodyPart.setText((String)mimeBodyText.get(i),"UTF-8"); (4)
          mimeMultipart.addBodyPart(mimeBodyPart);
          Vector filePathes = getFilePaths();
          for(int i = 0; i < filePathes.size(); i++)
          {
          String filePath = (String)filePathes.get(i);
          javax.activation.DataSource datasource = new FileDataSource(filePath);
          MimeBodyPart mimeFile = new MimeBodyPart();
          mimeFile.setDataHandler(new DataHandler(datasource));
          mimeFile.setFileName((new File(filePath)).getName());
          mimeMultipart.addBodyPart(mimeFile);
          }
          }
          catch(Exception e)
          {

          }
          return mimeMultipart;
          }






















          (1)

          設(shè)置發(fā)送地址,在手機上顯示發(fā)送方為該值


          (2)

          設(shè)置要發(fā)送到的手機號


          (3)

          手機上顯示的標題值,經(jīng)過筆者測試如果不指定編碼為UTF-8,手機上顯示為亂碼(測試手機京瓷), 不知道其他手機是否有這種情況。


          (4)

          手機上顯示的正文,經(jīng)過筆者測試如果不指定編碼為UTF-8,手機上顯示為亂碼(測試手機京瓷)。




          3、提交內(nèi)容到push接口


          public void write(String body)
          {
          java.io.OutputStream outStream = conn.getOutputStream(); (1)
          DataOutputStream dataOutStream = new DataOutputStream(outStream);
          dataOutStream.writeBytes(body);
          dataOutStream.flush();
          dataOutStream.close();
          }









          (1)

          這里的conn對象是引用第一步中實例的URLConnection對象,已經(jīng)處于open狀態(tài)。




          4、讀取push響應(yīng)信息


          提交信息與返回信息是實時的,因此應(yīng)該在提交后即實現(xiàn)讀取操作。


          public String responsePush()
          {
          StringBuffer sb = null;
          try
          {
          sb = new StringBuffer("");
          BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
          for(String line = null; (line = rd.readLine()) != null;)
          sb.append(line);
          rd.close();
          }
          catch(Exception ex)
          {

          }
          return new String(sb);
          }

          responsePush()得到的是一個標準的xml字符串。格式請參考接口指南。code節(jié)點的值為0代表push成功。

          posted on 2007-03-05 16:35 OMG 閱讀(333) 評論(0)  編輯  收藏 所屬分類: SSO/加密

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           

          <2007年3月>
          25262728123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          IT風云人物

          文檔

          朋友

          相冊

          經(jīng)典網(wǎng)站

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 微博| 延庆县| 台东市| 定日县| 延安市| 商丘市| 昌黎县| 晴隆县| 句容市| 溆浦县| 延安市| 抚宁县| 铜鼓县| 谷城县| 河源市| 崇州市| 泸州市| 南丹县| 元江| 庆城县| 洱源县| 得荣县| 宁阳县| 新巴尔虎左旗| 东莞市| 汶上县| 饶阳县| 兴仁县| 凤凰县| 阿荣旗| 彭山县| 南通市| 蓝田县| 德安县| 曲靖市| 大城县| 海门市| 诏安县| 云梦县| 衡东县| 博罗县|