前言

首先看一条链接:

https://github.com/Tencent/WeDemo

腾讯给了一个wedemo,微信第三方登录的例子。里面是php和ios,ios是object写的,php还是原来的php。

因为公司需要做android app微信第三方登录,所以我得写个android例子。心里是什么想法呢?

不就是Oauth 2.0,作为一个.net 看php也不是啥难处,写个app也没啥,结果遇到很多坑,好吧,我承认我是一只菜鸡。

下面是个人开发历程,如有思维错误请指导。

正文

我首先看到的是这张图:

上面这种图的故事告诉我们在操作资源性api(包括登录)之前呢,应该先建立安全通道。

流程是这样子的:

1.有一个32位字节的秘钥,(psk这是个通用名词,表示加密的key),使用的是aes,32位,那么就是aes256了。

//生成key
public static byte[] getAES256Key () throws NoSuchAlgorithmException
{
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256);
SecretKey sk = kg.generateKey();
//随机生成32位加密key
return sk.getEncoded();
}

2.把这个生成32位字节的秘钥去用公钥加密,这个公钥是写死在app中的,然后传给服务器。

private  String encryptedRSA(byte[] content) throws NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException, InvalidKeyException, UnsupportedEncodingException, ShortBufferException {
//base64编码的公钥
RSAPublicKey pubKey=getPublicKey();
//RSA加密
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
Map<String, String> param = Maps.newHashMap();
param.put("psk", new String(content));
String outStr = Base64.encodeBase64String(cipher.doFinal(com.alibaba.fastjson.JSON.toJSONString(param).getBytes()));
return outStr;
}

这里有个需要注意的就是要使用RSA/ECB/OAEPWithSHA-1AndMGF1Padding,因为服务端使用的是:OPENSSL_PKCS1_OAEP_PADDING,这个加密用的少,OAEP这种模式还是第一次听说,然后去查java的,原来是RSA/ECB/OAEPWithSHA-1AndMGF1Padding,

对我这种加解密不熟的人来说,算是一个小坑。

传这个流即可:

base64(public_encrypted(32秘钥))

这里有个非常值得注意的是,android app的base64和php的base64实现方式不一样,当时我调了好久(1个小时),然后通过打断点才知道base64实现不一样。

后来我就用库了,库的名称是:org.apache.commons.codec

这个库会产生冲突,需要把源码拿下来,然后改空间名,然后打包jar,最好还是网上找个吧,当时我是为了保险。

3.服务器去用私钥解开,然后保存psk(aes的key)。

4.将psk作为秘钥进行temp_uni加密传给客户端。

第四步,如果不看源码估计会被坑。

php关键源码:

public function AES_encode($data, $key)
{
$data = json_encode($data);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encode = $this->AES256_cbc_encrypt($data, $key, $iv);
// echo $encode;
$mac_server = hash_hmac('sha256', $encode, $key, true); // 计算mac_server
$encode = base64_encode($iv . $encode . $mac_server); // 加密后输出的格式为IV+AES密文+SHA256对AES密文进行哈希后的值
return $encode;
}

里面作为几件事:

1.生成一个16位的iv

2.用我们穿的key,和生成的iv,然后加密temp_in

3.对$encode和key进行hmac摘要。

4.iv和$encode还有hmac进行拼接,然后使用base64加密,发给客户端。

那么客户端需要做的就是下面几件事。

1.用base64解密开。

2.去处$encode,进行同样的hmac,得到的值和传过来的hmac比较,查看是否被串改数据。

3.使用保存在客户端的key和取下来的iv进行$encode解密,会得到一个json。

{'base_resp':{'errcode':$errcode,'errmsg':$errmsg},tmp_uin:'xxx'}

要取得就是tmp_uin。

好的,那么开始下一步。

取得了tmp_uin。那么用户就可以进行微信登录了。

用户点击后,会跳转到微信授权取得code。

那么客户端需要做的就是?因为这个图实在不清晰,那么我们来看下服务端做了啥,然后反推客户端应该干啥吧。

public function AES_decode($data, $key, $to_type = '')
{
$data = base64_decode($data);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = substr($data, 0, $iv_size);
$mac_client = substr($data, -32);
$encode = substr($data, $iv_size, -32);
$mac_server = hash_hmac('sha256', $encode, $key, true); // 计算mac_server
$decode = $this->AES256_cbc_decrypt($encode, $key, $iv);
// 检测包的合法性
if ($mac_client == $mac_server){
$decode = $this->AES256_cbc_decrypt($encode, $key, $iv);
if (!$decode) {
return null;
}
if ($to_type == 'json') {
$decode = json_decode($decode, true);
}
return $decode;
} else {
return null;
}
}

服务端解密模式和加密模式相对应,客户端应该做的是:

1.生成一个iv 16字节

2.使用原来的key,和生成的iv,对code进行加密,这里标注为encode。

3.生成一个hmac,数字摘要模式为sha256,也就是32字节的摘要。

4.拼接iv+encode+hmac进行base64位加密,然后发送为服务器端。

格式为:

{

"uin" : 3161321213,//上一步取得的temp_uni

"req_buffer" : "xxxx"//上文加密的数据

}

然后就会返回给我们正式通信后的内容,格式为:

Response: {

errcode : 0,

"resp_buffer" :"xxxx"//加密的数据

}

resp_buffer 里面包括了loginTicket和uni,作为以后和服务器的沟通凭据。

resp_buffer 进行解密的规则:和上文aes解密规则一致,这时候才真正的建立起正式的安全信道,

比如说获取用户信息:

按照上文的aes方法加密吧正式把uni和loignTicket 进行加密,就可以获得数据,然后又是客户端的解密获取用户信息,重复的就没什么坑了。

以上是个人遇到的坑和思路,也许会给刚入坑的人一点小小的帮助,如果思路哪里不好,也望请指点。

记写 android 微信登录的demo历程的更多相关文章

  1. Android微信登录、分享、支付

    转载需要著名出处: http://blog.csdn.net/lowprofile_coding/article/details/78004224 之前写过微信登录分享支付第一版: http://bl ...

  2. 解决Android微信支付官方demo运行失败

    Android微信支付官方demo运行失败,在此简单记录一下解决步骤 1.httpclient错误 官方给的demo是eclipse的,打开之后提示httpclient的错误,我知道在as下解决htt ...

  3. 详解Android微信登录与分享

    Android 使用微信登录.分享功能 具体的文档详情微信官网上介绍(微信官网文档),本人直接按照项目部署步骤进行讲解: 第一步:申请你的AppID: 第二步:依赖 dependencies { co ...

  4. android微信登录,分享

    这几天开发要用到微信授权的功能,所以就研究了一下.可是微信开放平台接入指南里有几个地方写的不清不楚.在此总结一下,以便需要的人. 很多微信公众平台的应用如果移植到app上的话就需要微信授权登陆了. 目 ...

  5. egret打包android + android微信登录--小结

    公司用egret做了款游戏,需要打android包,做安卓端的微信登录,于是乎开始了第一安卓上的打包,正的是一脸懵 首先遇到的问题有如下: 1. egret打安卓包时经常运行不起来, 主要是gradl ...

  6. Android实现登录小demo

    安卓,在小编实习之前的那段岁月里面,小编都没有玩儿过,如果说玩儿过,那就是安卓手机了,咳咳,敲登录的时候有种特别久违的熟悉,这种熟悉的感觉就和当时敲机房收费系统一样,那叫一个艰难啊,不过小编相信,在小 ...

  7. Android 微信第三方登录(个人笔记)

    今天在写微信登录,花了半天时间搞定.然后写下自己的笔记,希望帮助更多的人...欢迎各位指教. 微信授权登录,官方说的不是很清楚.所以导致有一部分的坑. 微信注册应用平台的应用签名,下载 微信签名生成工 ...

  8. 关于使用微信登录第三方APP的实现(Android版)

    使用微信登录APP,免去注册过程,现在已经有很多的类似应用了.集成该功能过程不复杂,但还是有一些地方需要注意的. 开始之前,需要做下面的准备工作. 1.到微信开放平台注册你的APP,并申请开通微信登录 ...

  9. android app使用微信登录接口回调没有被执行的问题研究

    本人开发的一个app使用了sharesdk集成微信登录功能,在测试的过程中微信授权登录界面有调用,但是授权后原应用的回调没有被执行 应用的包名是com.kimi.searcher 首先,确认微信点击授 ...

随机推荐

  1. 面试题五十七:和为s的数字

    题目一:和为s的数字,在一个递增数组中寻找两个数字的和等于s 方法:双指针法,一个在头一个在尾:如果两个指针指向的和小于,那么be++:大于end--: 题目二:打印所有和为s的连续正数序列 方法:双 ...

  2. 【IJCAI2020】Split to Be Slim: An Overlooked Redundancy in Vanilla Convolution

    Split to Be Slim: An Overlooked Redundancy in Vanilla Convolution, IJCAI 2020 论文地址: https://arxiv.or ...

  3. Redis之Redis入门介绍

    1.Redis概述    所谓Redis全称为REmote DIctionary Server(远程字典服务器) 是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key/value) ...

  4. macOS 遇到 svnadmin无法使用的情况

    首先,我在网上查了很多资料,大多数开发者都是表明了mac内置svn,然后直接使用svnadmin来创建仓库,但是我用命令行敲入svnadmin却显示找不到svnadmin.最开始,有个资料说用whic ...

  5. JVM详解之:HotSpot VM中的Intrinsic methods

    目录 简介 什么是Intrinsic Methods 内置方法的特点 多样性 兼容性 java语义的扩展 Hotspot VM中的内置方法 intrinsic方法和内联方法 intrinsic方法的实 ...

  6. PHP asort() 函数

    ------------恢复内容开始------------ 实例 对关联数组按照键值进行升序排序: <?php$age=array("Peter"=>"35 ...

  7. PHP curl_strerror函数

    (PHP 5 >= 5.5.0) curl_strerror — 返回错误码的描述. 说明 string curl_strerror ( int $errornum ) 返回错误码的文本描述信息 ...

  8. PHP date_interval_format() 函数

    ------------恢复内容开始------------ 计算两个日期间的间隔,然后格式化时间间隔: 实例 <?php $date1=date_create("2013-01-01 ...

  9. PHP asin() 函数

    实例 返回不同数的反正弦: <?phpecho(asin(0.64) . "<br>");echo(asin(-0.4) . "<br>&q ...

  10. 6.10 省选模拟赛 小C的利是 高斯消元 矩阵行列式

    LINK:小C的利是 想起来把这道题的题解写了 .一个常识:利是在广东那边叫做红包. 关于行列式的题目 不过我不太会23333..口胡还是可以的. 容易想到10分的状压.不过没什么意思. 仔细观察要求 ...