java和.net相互http请求并且经过des的cbc模式加密解密

来源:互联网 发布:php 实现域名跳转 编辑:程序博客网 时间:2024/04/29 17:09

前端时间接了个需求,要求是和.net的一下停做对接,说到底就是,互相http发送get'或者post请求,之间遇到了一些问题,记录下来

手下发下java发送http的post请求的代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;




public class HttpTest2 {

/**
     * 向指定 URL 发送POST方法的请求
     * 
     * @param url
     *            发送请求的 URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("content-type", "text/html");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!"+e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    } 
    
    
    public static void main(String[] args) {
   
        String sr=HttpTest2.sendPost("路径", “参数”);

        System.out.println(sr);
  
    }
}

这里有个问题必须要说明

因为我用的是struts2,这个地方我遇到一个问题,就是如果conn.setRequestProperty("content-type", "text/html");这个地方只能是text/html,如果改成application/x-www-form-urlencoded这样一直无法获取,这个原因不清楚,网上说struts2中必须是text/html,其他的无法获取。


然后就是加密和解密了 ,用的是des的cbs模式,代码如下

package com.besttone.commons;


import java.net.URLDecoder;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;


import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class DESUtil2 {

/**
  *
  * @return DES算法密钥
  */
  public static byte[] generateKey() {
       try {


           // DES算法要求有一个可信任的随机数源
           SecureRandom sr = new SecureRandom();


           // 生成一个DES算法的KeyGenerator对象
           KeyGenerator kg = KeyGenerator.getInstance("DES");
           kg.init(sr);


           // 生成密钥
           SecretKey secretKey = kg.generateKey();


           // 获取密钥数据
           byte[] key = secretKey.getEncoded();


           return key;
       } catch (NoSuchAlgorithmException e) {
           System.err.println("DES算法,生成密钥出错!");
           e.printStackTrace();
       }


       return null;
  }


  /**
  * 加密函数
  *
  * @param data
  *            加密数据
  * @param key
  *            密钥
  * @return 返回加密后的数据
  */
  public static byte[] encrypt(byte[] data, byte[] key) {


       try {


           // DES算法要求有一个可信任的随机数源
           SecureRandom sr = new SecureRandom();


           // 从原始密钥数据创建DESKeySpec对象
           DESKeySpec dks = new DESKeySpec(key);


           // 创建一个密匙工厂,然后用它把DESKeySpec转换成
           // 一个SecretKey对象
           SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
           SecretKey secretKey = keyFactory.generateSecret(dks);


           // using DES in ECB mode
           Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");


           // 用密匙初始化Cipher对象
           cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr);


           // 执行加密操作
           byte encryptedData[] = cipher.doFinal(data);


           return encryptedData;
       } catch (Exception e) {
           System.err.println("DES算法,加密数据出错!");
           e.printStackTrace();
       }


       return null;
  }


  /**
  * 解密函数
  *
  * @param data
  *            解密数据
  * @param key
  *            密钥
  * @return 返回解密后的数据
  */
  public static byte[] decrypt(byte[] data, byte[] key) {
       try {
           // DES算法要求有一个可信任的随机数源
           SecureRandom sr = new SecureRandom();


           // byte rawKeyData[] = /* 用某种方法获取原始密匙数据 */;


           // 从原始密匙数据创建一个DESKeySpec对象
           DESKeySpec dks = new DESKeySpec(key);


           // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
           // 一个SecretKey对象
           SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
           SecretKey secretKey = keyFactory.generateSecret(dks);


           // using DES in ECB mode
           Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");


           // 用密匙初始化Cipher对象
           cipher.init(Cipher.DECRYPT_MODE, secretKey, sr);


           // 正式执行解密操作
           byte decryptedData[] = cipher.doFinal(data);


           return decryptedData;
       } catch (Exception e) {
           System.err.println("DES算法,解密出错。");
           e.printStackTrace();
       }


       return null;
  }


  /**
  * 加密函数
  *
  * @param data
  *            加密数据
  * @param key
  *            密钥
  * @return 返回加密后的数据
  */
  public static byte[] CBCEncrypt(byte[] data, byte[] key, byte[] iv) {


       try {
           // 从原始密钥数据创建DESKeySpec对象
           DESKeySpec dks = new DESKeySpec(key);


           // 创建一个密匙工厂,然后用它把DESKeySpec转换成
           // 一个SecretKey对象
           SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
           SecretKey secretKey = keyFactory.generateSecret(dks);


           // Cipher对象实际完成加密操作
           Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
           // 若采用NoPadding模式,data长度必须是8的倍数
           // Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");


           // 用密匙初始化Cipher对象
           IvParameterSpec param = new IvParameterSpec(iv);
           cipher.init(Cipher.ENCRYPT_MODE, secretKey, param);


           // 执行加密操作
           byte encryptedData[] = cipher.doFinal(data);


           return encryptedData;
       } catch (Exception e) {
           System.err.println("DES算法,加密数据出错!");
           e.printStackTrace();
       }


       return null;
  }


  /**
  * 解密函数
  *
  * @param data
  *            解密数据
  * @param key
  *            密钥
  * @return 返回解密后的数据
  */
  public static byte[] CBCDecrypt(byte[] data, byte[] key, byte[] iv) {
       try {
           // 从原始密匙数据创建一个DESKeySpec对象
           DESKeySpec dks = new DESKeySpec(key);


           // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
           // 一个SecretKey对象
           SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
           SecretKey secretKey = keyFactory.generateSecret(dks);


           // using DES in CBC mode
           Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
           // 若采用NoPadding模式,data长度必须是8的倍数
           // Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");


           // 用密匙初始化Cipher对象
           IvParameterSpec param = new IvParameterSpec(iv);
           cipher.init(Cipher.DECRYPT_MODE, secretKey, param);


           // 正式执行解密操作
           byte decryptedData[] = cipher.doFinal(data);


           return decryptedData;
       } catch (Exception e) {
           System.err.println("DES算法,解密出错。");
           e.printStackTrace();
       }


       return null;
  }


  public static void main(String[] args) {
  try {
           byte[] key = "NEMOBIlE".getBytes("utf-8");
           byte[] iv = "NEMOBIlE".getBytes("utf-8");
           byte[] data = DESUtil2.CBCEncrypt("XXXXX".getBytes("utf-8"), key, iv);
           //加密转换  
           BASE64Encoder enc = new BASE64Encoder(); 
           
           BASE64Decoder dec = new BASE64Decoder(); 
           String encryptedtext = enc.encode(data); 
           System.out.println("加密后:" + encryptedtext);
           System.out.println("加密后:" + java.net.URLEncoder.encode(encryptedtext,"utf-8"));
           String aaa= java.net.URLDecoder.decode(java.net.URLEncoder.encode(encryptedtext,"utf-8"),"utf-8");
           byte[] resultArr = dec.decodeBuffer(aaa);
           System.out.println("解密后:" + new String(DESUtil2.CBCDecrypt(resultArr, key, iv)));
           
       } catch (Exception e) {
           e.printStackTrace();
       }
  } 
}

这里需要说明的是,如果是post请求,一般加过密后就不需要做.URLEncoder.encode的操作了,获取进行解密就行,但是如果是url的方式,

那么加密后必须要做URLEncoder.encode转换的,然后获取在直接进行解密,不然会出现问题的,

下面发下  .net的des加密代码

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
 
using System.Security.Cryptography;
using System.IO;
using System.Text;


namespace MobileCommonPay.Tool
{
    public class DES2
    {


        // CBC模式


        string iv = "NEMOBIlE";
        string key = "NEMOBIlE";


        /// <summary>
        /// DES加密偏移量,必须是>=8位长的字符串
        /// </summary>
        public string IV
        {
            get { return iv; }
            set { iv = value; }
        }


        /// <summary>
        /// DES加密的私钥,必须是8位长的字符串
        /// </summary>
        public string Key
        {
            get { return key; }
            set { key = value; }
        }


        /// <summary>
        /// 对字符串进行DES加密
        /// </summary>
        /// <param name="sourceString">待加密的字符串</param>
        /// <returns>加密后的BASE64编码的字符串</returns>
        public string Encrypt(string sourceString)
        {
            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            using (MemoryStream ms = new MemoryStream())
            {
                byte[] inData = Encoding.Default.GetBytes(sourceString);
                try
                {
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(inData, 0, inData.Length);
                        cs.FlushFinalBlock();
                    }
                    return Convert.ToBase64String(ms.ToArray());
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            }
        }


        /// <summary>
        /// 对DES加密后的字符串进行解密
        /// </summary>
        /// <param name="encryptedString">待解密的字符串</param>
        /// <returns>解密后的字符串</returns>
        public string Decrypt(string encryptedString)
        {
            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();


            using (MemoryStream ms = new MemoryStream())
            {
                byte[] inData = Convert.FromBase64String(encryptedString);
                try
                {
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(inData, 0, inData.Length);
                        cs.FlushFinalBlock();
                    }
                    return Encoding.Default.GetString(ms.ToArray());
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            }
        }


        /// <summary>
        /// 对文件内容进行DES加密
        /// </summary>
        /// <param name="sourceFile">待加密的文件绝对路径</param>
        /// <param name="destFile">加密后的文件保存的绝对路径</param>
        public void EncryptFile(string sourceFile, string destFile)
        {
            if (!File.Exists(sourceFile)) throw new FileNotFoundException("指定的文件路径不存在!", sourceFile);


            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] btFile = File.ReadAllBytes(sourceFile);


            using (FileStream fs = new FileStream(destFile, FileMode.Create, FileAccess.Write))
            {
                try
                {
                    using (CryptoStream cs = new CryptoStream(fs, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(btFile, 0, btFile.Length);
                        cs.FlushFinalBlock();
                    }
                }
                catch
                {
                    throw;
                }
                finally
                {
                    fs.Close();
                }
            }
        }


        /// <summary>
        /// 对文件内容进行DES加密,加密后覆盖掉原来的文件
        /// </summary>
        /// <param name="sourceFile">待加密的文件的绝对路径</param>
        public void EncryptFile(string sourceFile)
        {
            EncryptFile(sourceFile, sourceFile);
        }


        /// <summary>
        /// 对文件内容进行DES解密
        /// </summary>
        /// <param name="sourceFile">待解密的文件绝对路径</param>
        /// <param name="destFile">解密后的文件保存的绝对路径</param>
        public void DecryptFile(string sourceFile, string destFile)
        {
            if (!File.Exists(sourceFile)) throw new FileNotFoundException("指定的文件路径不存在!", sourceFile);


            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] btFile = File.ReadAllBytes(sourceFile);


            using (FileStream fs = new FileStream(destFile, FileMode.Create, FileAccess.Write))
            {
                try
                {
                    using (CryptoStream cs = new CryptoStream(fs, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(btFile, 0, btFile.Length);
                        cs.FlushFinalBlock();
                    }
                }
                catch
                {
                    throw;
                }
                finally
                {
                    fs.Close();
                }
            }
        }


        /// <summary>
        /// 对文件内容进行DES解密,加密后覆盖掉原来的文件
        /// </summary>
        /// <param name="sourceFile">待解密的文件的绝对路径</param>
        public void DecryptFile(string sourceFile)
        {
            DecryptFile(sourceFile, sourceFile);
        }
    }
}


.net中加密解密的问题,主要就是编码Encoding.Default这样默认的就不是utf-8了,这样加密出问题,这个时候要换成Encoding.GetEncoding("UTF-8")这样就可以了,

最后说下,对接真是麻烦,遇到好说话的人还好,如果遇到一些不好搞的人,那真是头疼的........

0 0
原创粉丝点击