记写 android 微信登录的demo历程
前言
首先看一条链接:
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历程的更多相关文章
- Android微信登录、分享、支付
转载需要著名出处: http://blog.csdn.net/lowprofile_coding/article/details/78004224 之前写过微信登录分享支付第一版: http://bl ...
- 解决Android微信支付官方demo运行失败
Android微信支付官方demo运行失败,在此简单记录一下解决步骤 1.httpclient错误 官方给的demo是eclipse的,打开之后提示httpclient的错误,我知道在as下解决htt ...
- 详解Android微信登录与分享
Android 使用微信登录.分享功能 具体的文档详情微信官网上介绍(微信官网文档),本人直接按照项目部署步骤进行讲解: 第一步:申请你的AppID: 第二步:依赖 dependencies { co ...
- android微信登录,分享
这几天开发要用到微信授权的功能,所以就研究了一下.可是微信开放平台接入指南里有几个地方写的不清不楚.在此总结一下,以便需要的人. 很多微信公众平台的应用如果移植到app上的话就需要微信授权登陆了. 目 ...
- egret打包android + android微信登录--小结
公司用egret做了款游戏,需要打android包,做安卓端的微信登录,于是乎开始了第一安卓上的打包,正的是一脸懵 首先遇到的问题有如下: 1. egret打安卓包时经常运行不起来, 主要是gradl ...
- Android实现登录小demo
安卓,在小编实习之前的那段岁月里面,小编都没有玩儿过,如果说玩儿过,那就是安卓手机了,咳咳,敲登录的时候有种特别久违的熟悉,这种熟悉的感觉就和当时敲机房收费系统一样,那叫一个艰难啊,不过小编相信,在小 ...
- Android 微信第三方登录(个人笔记)
今天在写微信登录,花了半天时间搞定.然后写下自己的笔记,希望帮助更多的人...欢迎各位指教. 微信授权登录,官方说的不是很清楚.所以导致有一部分的坑. 微信注册应用平台的应用签名,下载 微信签名生成工 ...
- 关于使用微信登录第三方APP的实现(Android版)
使用微信登录APP,免去注册过程,现在已经有很多的类似应用了.集成该功能过程不复杂,但还是有一些地方需要注意的. 开始之前,需要做下面的准备工作. 1.到微信开放平台注册你的APP,并申请开通微信登录 ...
- android app使用微信登录接口回调没有被执行的问题研究
本人开发的一个app使用了sharesdk集成微信登录功能,在测试的过程中微信授权登录界面有调用,但是授权后原应用的回调没有被执行 应用的包名是com.kimi.searcher 首先,确认微信点击授 ...
随机推荐
- Python学习手册(第4版)PDF高清完整版免费下载|百度云盘
Python学习手册(第4版)PDF高清完整版免费下载|百度云盘 提取码:z6il 内容简介 Google和YouTube由于Python的高可适应性.易于维护以及适合于快速开发而采用它.如果你想要编 ...
- scp的使用以及cp的对比
scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...
- python匿名函数和内置函数
一.匿名函数 匿名函数定义lambda a,b,c:(x,y,z) a.b.c相当于形参,多个形参之间用逗号隔开,多个形参不能用括号括起来 (x.y.z)相当于返回值,多个返回值之间用逗号隔开,多个返 ...
- Java线程池ThreadPoolExecutor面试总结思维导图速记
优点 降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度,当任务到达时,可以不需要等待线程创建就能立即执行. 提高线程的可管理性 类关系 接 Executor 一个无返 ...
- circle踢人(约瑟夫环) c++
这里更新指针法,真的每句都是坑 (寥寥数十句,句句都是坑) // // Created by snnnow on 2020/4/12. //question:转圈,一共N个人,数到M的出列,求最后一个 ...
- matplotlib基础汇总_01
灰度化处理就是将一幅色彩图像转化为灰度图像的过程.彩色图像分为R,G,B三个分量,分别显示出红绿蓝等各种颜色,灰度化就是使彩色的R,G,B分量相等的过程.灰度值大的像素点比较亮(像素值最大为255,为 ...
- Python Tuple(元组) min()方法
描述 Python 元组 min() 函数返回元组中元素最小值.高佣联盟 www.cgewang.com 语法 min()方法语法: min(tuple) 参数 tuple -- 指定的元组. 返回值 ...
- PHP unset() 函数
unset() 函数用于销毁给定的变量.高佣联盟 www.cgewang.com PHP 版本要求: PHP 4, PHP 5, PHP 7 语法 void unset ( mixed $var [, ...
- PHP chr() 函数
实例 从不同 ASCII 值返回字符: <?php高佣联盟 www.cgewang.comecho chr(52) . "<br>"; // Decimal va ...
- C/C++编程笔记:C语言入门知识点(二),请收藏C语言最全笔记!
今天我们继续来学习C语言的入门知识点 11. 作用域规则 任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问.C 语言中有三个地方可以声明变量: 在函数或块内部的局部变量 ...