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

news2025/1/16 14:12:47

如果你对于网络请求用了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(),拿到字符串自己解析。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1154403.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

私有网络的安全保障,WorkPlus Meet内网视频会议助力企业高效会议

在企业内部沟通与协作中,视频会议成为了一种必不可少的沟通方式。然而,传统的互联网视频会议往往受制于网络不稳定因素,给企业带来不便与困扰。WorkPlus Meet作为一款专注内网视频会议的软件,致力于为企业打造高效、稳定的内网视频…

openpnp - code review - 开机对话框历史记录和贡献者名单

文章目录 openpnp - code review - 开机对话框历史记录和贡献者名单概述笔记D:\my_openpnp\openpnp_dev_2022_0801\src\main\java\org\openpnp\gui\AboutDialog.javaEND openpnp - code review - 开机对话框历史记录和贡献者名单 概述 偶然发现, 自己打包后的openpnp, 开机后…

js中获取json的值:使用 JSON.parse() 方法

比如json为:configs: "{"type":1}" 直接打印configs如下图 我们可以使用 JSON.parse() 方法将JSON格式字符串转换为 JavaScript 对象。 let a JSON.parse(configs) console.log(a) a打印出来如下图 此时就可以用a.type来得到1。 JSON.parse(…

配电柜监控原来还能这样?真的太爽啦!

在现代社会中,电力作为基础设施的一部分,扮演着至关重要的角色。为了确保电力系统的可靠性、安全性和高效性,配电柜监控系统变得越来越重要。 配电柜监控系统提供了实时数据和控制,有助于迅速识别并解决问题,从而降低停…

Linux 远程桌面软件

为您的 IT 管理员配备最好的 Linux 远程桌面软件至关重要。原因如下?Linux 是一个开源和免费的操作系统,它提供了一个非常灵活和可定制的软件内核。由于其开源性质,Linux 被认为是市场上最安全的操作系统之一,它拥有一个全球用户社…

【学习SonarQube记录】如何在windows上安装SonarQube及安装中文语言包

学习SonarQube记录 第一章 如何在windows上安装SonarQube及安装中文语言包 文章目录 学习SonarQube记录前言一、SonarQube是什么?二、安装步骤1.准备工作2.安装SonarQube 总结 前言 公司近期有代码完整性检测的需求,于是来学习相关工具SonarQube 一、S…

算法:二叉树难题和与STL相结合的练习题

文章目录 二叉树层序遍历原理二叉树的层序遍历 二叉树的最近公共祖先二叉搜索树和双向链表从前序与中序遍历序列构造二叉树从后序与中序遍历序列构造二叉树二叉树的非递归实现前序遍历中序遍历后序遍历 二叉树层序遍历原理 二叉树的层序遍历通常是借助队列来实现,可…

数字孪生应用到供水站远程运维的场景及优势

水厂在生活中的重要性不可忽视。它们提供清洁、安全的水源,满足人们饮用、洗浴、烹饪等基本需求,保障公共卫生,预防疾病传播;同时,水厂也促进经济发展,为工业生产和农业灌溉提供保障,吸引和支持企业的投资和…

【产品经理从0到1】ID(工业设计)知识构建

导语:作为一个硬件产品经理,虽然不需要自己进行工业设计,但是若要对产品外观和品质细节进行更深入和准确的把控,就需要了解工业设计的相关知识。

微信小程序-授权登录(手机号码)

1、WXBizDataCrypt.js-下载地址 2、UNIAPP代码 <template> <view class"work-container"> <view class"login"> <view class"content"> <button class"button_wx&q…

Intel 系列时序说明

1xx2xx系列时序说明 1.VCCRTC=2.5V+ 3.3V BOARD TO PCH 保存CMOS信息,保持时钟正常运行 电池供电或3V线性给到 2.RTCRST#/SRTCRST# BOARD TO PCH 延时复位 正常3.3V,低到高完成复位,VCCRTC通过电阻延时 3.32.768KHZ=RTCX1 BOARD TO PCH 0.1V-0.6V直通桥 4.VC…

关键词搜索天猫商品数据接口(标题|主图|SKU|价格|优惠价|掌柜昵称|店铺链接|店铺所在地|天猫商品列表API接口)

关键词搜索天猫商品数据接口可以使用天猫官方的API接口实现。以下是一些可能有用的天猫API接口&#xff1a; item_search_tmall - 按关键字搜索天猫商品接口&#xff1a;这个接口可以用于通过关键词搜索天猫商品&#xff0c;获取商品列表。可以在接口中使用不同的关键字进行搜…

关于有效客户关系管理,你需要了解的一切

为了了解客户购买决策的驱动因素或阻碍因素&#xff0c;你需要组织和分析有关客户需求、喜好和厌恶的数据。这正是客户关系管理其中一个重要方面。有效的客户关系管理可以帮助企业与其现有客户和潜在客户建立联系&#xff0c;以提高客户满意度并确保销售周期有利可图。 什么是客…

【HTML】实现填写简历信息

实现页面&#xff1a; 完整源代码&#xff1a; <!DOCTYPE html> <html lang"cn"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Doc…

Jt808应答举例

1.前言 最近客户在集成基于Jt808的产品协议的时候&#xff0c;经常会遇到一些问题&#xff0c;比如没有进行转义&#xff0c;或者转义的时机不对&#xff0c;导致校验码没有进行转义。为了让大家更熟悉Jt808的指令组包&#xff0c;我这里整理了一下转义的步骤。 2.组包 以此…

android 8.1 disable unsupported sensor

如果device不支持某种sensor,可以在android/frameworks/base/core/java/android/hardware/SystemSensorManager.java里将其disabled掉。以disable proximity sensor为例。 public SystemSensorManager(Context context, Looper mainLooper) {synchronized(sLock) {if (!sNativ…

mysql---DCL(用户创建及限制)

DCL: 权限控制语句 grant revoke 数据库用户管理: 创建用户 修改用户的权限 删除用户 grant 要在终端执行。 用户创建语句注释 create user ky32localhost identified by 123456; create user 创建用户的开头 ky32localhost ky32 表示用户的主机名 localhost 新建的…

一文吃透低代码开发与传统IT开发的区别

目录 一、含义不同 二、开发门槛不同 三、两者之间的区别 1、从技术特征来看 2、从目标开发者来看 四、低代码平台使用感受&#xff1f; &#xff08;1&#xff09;自定义模块&#xff0c;满足不同的业务需求 &#xff08;2&#xff09;工作流引擎&#xff0c;简化复杂流程的管…

js判断数据类型的方式详解(面试题)

一.typeof 1.用来判断基本数据类型 null、Object、String判断的结果都为object 二.instanceof 检测构造函数的 prototype 属性是否在某个实例对象的原型链上 不能判断简单数据类型&#xff0c;只能判断复杂数据类型。 复杂数据类型的具体类型不一定判断正确。 手写instanceof…

[软件下载]解决copperliasim(原v-rep)的教育版无法下载的问题

前言 v-rep&#xff08;现在叫做copperliasim,但是v-rep字数比较少&#xff0c;并且叫的人也比较多&#xff0c;故下文皆称vrep&#xff09;是一款优秀的机器人仿真软件&#xff0c;在国内似乎用的人不多&#xff0c;但是国外据说还是比较流行的。 目前或许有不少的朋友在下载…