Android登录注册功能加密处理

22 篇文章 2 订阅
8 篇文章 0 订阅

Android使用OKhttp3实现登录注册功能+springboot搭建后端》这篇教程介绍了登录注册的流程及基本实现。但是有一些小问题。就是后端处理的时候,URL将用户名密码使用明文加密。这样抓包就很容易获取隐私数据。这篇完善这个问题。例如这个网站,我们进行抓包获取到请求,这里的密码是加密的。
请添加图片描述
加密算法分为对称加密和非对称加密。这里我们就简单介绍如何使用加密算法来实现这个功能(主要强调的是流程)。

一、Android前端

这里使用AES对称加密算法

1、创建AESHelper.java

import java.io.UnsupportedEncodingException;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
///** AES对称加密解密类 **/
public class AESHelper {
    // /** 算法/模式/填充 **/
    private static final String CipherMode = "AES/ECB/PKCS5Padding";
    ///** 创建密钥 **/
    private static SecretKeySpec createKey(String password) {
        byte[] data = null;
        if (password == null) {
            password = "";
        }
        StringBuffer sb = new StringBuffer(32);
        sb.append(password);
        while (sb.length() < 32) {
            sb.append("0");
        }
        if (sb.length() > 32) {
            sb.setLength(32);
        }
        try {
            data = sb.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new SecretKeySpec(data, "AES");
    }
    // /** 加密字节数据 **/
    public static byte[] encrypt(byte[] content, String password) {
        try {
            SecretKeySpec key = createKey(password);
            System.out.println(key);
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    ///** 加密(结果为16进制字符串) **/
    public static String encrypt(String content, String password) {
        byte[] data = null;
        try {
            data = content.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        data = encrypt(data, password);
        String result = byte2hex(data);
        return result;
    }
    // /** 解密字节数组 **/
    public static byte[] decrypt(byte[] content, String password) {
        try {
            SecretKeySpec key = createKey(password);
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    ///** 解密16进制的字符串为字符串 **/
    public static String decrypt(String content, String password) {
        byte[] data = null;
        try {
            data = hex2byte(content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        data = decrypt(data, password);
        if (data == null)
            return null;
        String result = null;
        try {
            result = new String(data, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }
    // /** 字节数组转成16进制字符串 **/
    public static String byte2hex(byte[] b) { // 一个字节的数,
        StringBuffer sb = new StringBuffer(b.length * 2);
        String tmp = "";
        for (int n = 0; n < b.length; n++) {
            // 整数转成十六进制表示
            tmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (tmp.length() == 1) {
                sb.append("0");
            }
            sb.append(tmp);
        }
        return sb.toString().toUpperCase(); // 转成大写
    }
    // /** 将hex字符串转换成字节数组 **/
    private static byte[] hex2byte(String inputString) {
        if (inputString == null || inputString.length() < 2) {
            return new byte[0];
        }
        inputString = inputString.toLowerCase();
        int l = inputString.length() / 2;
        byte[] result = new byte[l];
        for (int i = 0; i < l; ++i) {
            String tmp = inputString.substring(2 * i, 2 * i + 2);
            result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF);
        }
        return result;
    }
}

2、修改MainActivity.java

这里修改login方案的算法

public void login(View view) {
        loginUser = new LoginUser();
        loginUser.setUserName(username.getText().toString());
        loginUser.setUserPassword(password.getText().toString());
        new Thread(new Runnable() {
            @Override
            public void run() {
                MediaType JSON = MediaType.parse("application/json;charset=utf-8");
                JSONObject jsonObject = new JSONObject();
                OkHttpClient httpClient = new OkHttpClient();
                try {
                    jsonObject.put("userName",loginUser.getUserName());
                    jsonObject.put("userPassword",loginUser.getUserPassword());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                //7.29 对数组进行加密解密,后端解密,前端加密,秘钥为"key",这里的key自行设定与后端对应即可;
                String encrypt = AESHelper.encrypt(jsonObject.toString(), "key");

//                RequestBody requestBody = RequestBody.create(JSON, String.valueOf(jsonObject));
                RequestBody requestBody = RequestBody.create(JSON, encrypt);


                Log.d("前端测试发送的jsonObject:",jsonObject.toString());
                Log.d("encrypt:",encrypt);
                Log.d("前端测试发送的requestBody:",requestBody.toString());
//                String url = "http://ip:8001/server/user/login";
                String url = "http://ip:8001/server/user/loginaes";
                Request request = new Request.Builder()
                        .url(url)
                        .post(requestBody)
                        .build();
                Log.d("前端测试发送的request:",request.toString());

                Call call = httpClient.newCall(request);
                call.enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        Log.d("whq登录","失败了");
                    }
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String MyResult = response.body().string();
                      /*  Gson gson = new GsonBuilder().create();
                        ResultGson resultGson = gson.fromJson(MyResult, ResultGson.class);

                        Log.d("whq登录",resultGson.getData().get("result")+"---------resultGson---------");
                        Log.d("whq登录",resultGson.toString()+"---------resultGson---------");*/

                       /* Log.d("whq登录","----------------------------");
                        Map<String, Object> data = new HashMap<String, Object>();
                        data.put("result","success login");
                        ResultGson json = new ResultGson(true, 20000, "成功", data);
                        Log.d("原始json",json.toString());
                        Gson gson1 = new GsonBuilder().create();
                        String toJson = gson1.toJson(json);
                        Log.d("转化之后的json",toJson);*/
                        Log.d("whq登录",response+"---------response---------");
                        Log.d("whq登录",response.message()+"---------message---------");
                        Log.d("whq登录",response.body().toString()+"------------------");
                        Log.d("whq登录",MyResult+"-----------MyResult-------");
                        Log.d("whq登录",MyResult.contains("success login")+"-----------MyResult.length()-------");
                    }
                });
            }
        }).start();
    }

注意这里修改了三处地方:

//7.29 对数组进行加密解密,后端解密,前端加密,秘钥为key;
String encrypt = AESHelper.encrypt(jsonObject.toString(), "key");
//RequestBody requestBody = RequestBody.create(JSON, String.valueOf(jsonObject));
RequestBody requestBody = RequestBody.create(JSON, encrypt);
//String url = "http://ip:8001/server/user/login";
String url = "http://ip:8001/server/user/loginaes";

将json加密成字符串,这里的key自行设定,需要与后端对应解密。使用新的URL请求地址。这样前端就修改完成,就是这么简单。

二、服务器后端

1、创建AESHelper.java类

这个类与Android端的工具类一样,复制过来就行。

1、修改UserController.java

    @PostMapping("loginaes")
    public R loginAES(@RequestBody String Aes){
        String decrypt = AESHelper.decrypt(Aes,"key");
        System.out.println("decrypt"+decrypt);
        Gson gson = new GsonBuilder().create();
        loginUser loginUser = gson.fromJson(decrypt, loginUser.class);
        System.out.println("loginUser"+loginUser.toString());
        System.out.println("loginUser"+loginUser);
        String token = userService.login(loginUser);
        if (token == "wrong Password"){
            return R.error().data("result",token);
        }else{
            return R.ok().data("result",token);
        }
    }

这里重新修改接口,定义一个loginaes的接口,将参数先解密,这里的key要对应起来,由于是字符串,我们需要将字符串转为json,这里使用GSon工具,具体介绍看这篇文章《Android解析json-Gson使用》,这里还要有一个loginUser的实体类
loginUser.java

@Data
public class loginUser {
    private String userName;
    private String userPassword;
}

其他的地方不需要改动。

三、启动项目

使用maven将项目打包部署在服务器上,参考之前的教程,安装APP进行调试
在这里插入图片描述
抓包:
在这里插入图片描述
这样就解决了明文传送。当然还可以使用其他的非对称加密算法,生成双钥就可以了(比如RSA算法)。也可以继续改进加密的功能,这里只是粗略的介绍一下思想。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值