okhttp post请求 header post参数加密遇到的两个问题

如果你对于网络请求用了https后是否还有必要对参数加密有疑问可以看我上篇的文章:网络安全https 记得耐心看完,下面说问题:

  1. Caused by: java.lang.IllegalArgumentException: Unexpected char 0x0a 一开始以为是okhttp框架对特殊字符做了现在,网上其他文章说的是对中文字符,我想我这也没中文啊,但还是全部换成原生试了一下,果然,还是一样报错,坑爹的网友啊,哈哈!
    下面是测试用例demo的代码
package com.tcssj.mbjmb;

import android.util.Base64;
import android.view.View;

import java.nio.charset.StandardCharsets;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESUtil2 {
    public static byte[] base64ToDecode(String str) {
        byte[] byteStr = Base64.decode(str, Base64.DEFAULT);
        return byteStr;
    }

    public static String encode(byte[] key) {
        return Base64.encodeToString(key, Base64.NO_WRAP);
    }

    /**
     * 加密
     *
     * @param content 需要加密的内容
     * @param key     加密密码
     * @return
     */
    public static String encrypt(String content, String key) {
        return encrypt(content,key.getBytes());
    }

    public static String encrypt(String content, byte[] key) {
        try {
            //构造密钥
            SecretKeySpec skey = new SecretKeySpec(key, "utf-8");
            //创建初始向量iv用于指定密钥偏移量(可自行指定但必须为128位),因为AES是分组加密,下一组的iv就用上一组加密的密文来充当
            IvParameterSpec iv = new IvParameterSpec(key, 0, 16);
            //创建AES加密器
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
            //使用加密器的加密模式
            cipher.init(Cipher.ENCRYPT_MODE, skey, iv);
            // 加密
            byte[] result = cipher.doFinal(byteContent);
            //使用BASE64对加密后的二进制数组进行编码
            return encode(result);
        } catch (Exception e) {
            e.printStackTrace();
            return content;
        }
    }

    /**
     * 解密
     * @param content
     * @param key
     * @return
     */
    public static String decrypt(String content,  byte[] key) {
        try {

            SecretKeySpec skey = new SecretKeySpec(key, "utf-8");
            IvParameterSpec iv = new IvParameterSpec(key, 0, 16);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //解密时使用加密器的解密模式
            // 初始化
            cipher.init(Cipher.DECRYPT_MODE, skey, iv);
            byte[] result = cipher.doFinal(base64ToDecode(content));
            // 解密
            return new String(result);
        } catch (Exception e) {
            return content;
        }
    }
}

package com.tcssj.mbjmb

import android.os.Bundle
import android.os.Handler
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.tcssj.mbjmb.ui.theme.MbjmbTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import okhttp3.Headers
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import org.json.JSONObject

class MainActivity : ComponentActivity() ,test {
    private  val TAG = "MainActivity"
    lateinit var  text:String
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
   runBlocking(Dispatchers.IO) {
       val okHttpClient=OkHttpClient()
//        val build=okHttpClient.newBuilder()
       val jsonpost=JSONObject()
       jsonpost.put("type","text")
       jsonpost.put("mobile","81991419936")
       val body=RequestBody.create(MediaType.parse("application/json;charset=utf-8"),AESUtil2.encrypt(jsonpost.toString(),AESUtil2.base64ToDecode("allWUzg1eFJ3ekpNQklUeQ==")))

       val json=JSONObject()
       json.put("sourceChannel","Orange")
       json.put("packageName","com.tcssj.mbjmb")
       json.put("adid","")
       json.put("version","12.0.0")
       json.put("uuId","")
       json.put("userId","")
       val request= Request.Builder().url("http://47.101.194.189:10018/auth/v3.1/user/sendVerifiyCode")
           .header("HCFQ",AESUtil2.encrypt(json.toString(), "xDBrgJdnnY2w1Do7Ik6otonXQRgQyt46"))
           .header("packageName","mbjmb")
           .post(body)
           .build()

       val response= okHttpClient.newCall(request).execute()
       response.toString()
       text=AESUtil2.decrypt(response.body().string(), AESUtil2.base64ToDecode("allWUzg1eFJ3ekpNQklUeQ=="))
       Log.i(TAG, "onCreate: "+AESUtil2.decrypt(text, AESUtil2.base64ToDecode("allWUzg1eFJ3ekpNQklUeQ==")))
   }
        setContent {
            MbjmbTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Greeting(name =text)
                }
            }
        }



    }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "$name!",
        modifier = modifier
    )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MbjmbTheme {
        Greeting("Android")
    }
}

第一个问题的原因就是我们参数进行加密后有换行符号\n,怎么解决呢?如下图,划线的部分你如果是用的Default,那就会报第一个错误,你需要使用NO_WRAP 不生成换行符的。
在这里插入图片描述
第二个坑就是返回的也是加密后的乱码,你需要拿回来解密的,那你下图中就不能使用body.toString() 方法,要用String()方法。(我是怎么发现的,我用apifox 工具(如果你接口调试还没使用上,拿走不谢,还是要用这么个工具,不然你来来回回启动app调试接口效率很低,但你会懒的使用,抗拒学新的,人吗,天性,但你要克服)调试接口的时候,发现工具和android里面的返回结果不一致)
在这里插入图片描述
因为看下图,如果你用了toString 方法 message当时空的,整个是空的框架,加密的内容okhttp无法转换成它的结构,那你就要用string(),拿到字符串自己解析。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OkHttp 是一个开源的 HTTP 客户端,它是由 Square 公司贡献的一个轻量级框架,用于处理 Java 和 Android 应用程序的 HTTP 请求。其中,OkHttp 提供了丰富的请求方法,包括 GET、POST、PUT、DELETE 等等。而 OkHttpPOST 请求方法主要用于向服务器提交数据。 下面是一个简单的 OkHttp POST 请求的示例代码: ``` OkHttpClient client = new OkHttpClient(); MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); RequestBody body = RequestBody.create(mediaType, "{\"username\":\"admin\",\"password\":\"123456\"}"); Request request = new Request.Builder() .url("http://example.com/api/login") .post(body) .addHeader("Content-Type", "application/json") .build(); Response response = client.newCall(request).execute(); String responseData = response.body().string(); ``` 在这个示例中,我们首先创建了一个 OkHttpClient 对象,然后定义了请求体的数据格式(application/json),并创建了一个 RequestBody 对象来存储请求体的内容。接下来,我们创建了一个 Request 对象,并通过调用 post() 方法来指定请求方法为 POST,并将前面创建的 RequestBody 对象作为参数传入。在构造完整的 Request 对象后,我们可以通过 addHeader() 方法添加请求头信息。最后,我们通过调用 OkHttpClient 对象的 newCall() 方法来发送请求,并通过调用 execute() 方法来执行该请求并获取响应结果。最终,我们可以通过调用 response.body().string() 方法获取响应体中的内容。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值