记写 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 首先,确认微信点击授 ...
随机推荐
- springMVC(二)springMVC、Mybatis、spring整合
数据库设置: 一.配置文件设置 (1).springMVC配置文件(前端控制器web.xml,核心配置文件springmvc.xml) <?xml version="1.0" ...
- Ionic 移动端
<body ng-app="testApp"> <ion-header-bar align-title="left" class=" ...
- numpy的random方法和常用数据类型
NumPy 的常用数据类型 np.random 随机数模块
- PHP lcfirst() 函数
实例 把 "Hello" 的首字符转换为小写.: <?php高佣联盟 www.cgewang.comecho lcfirst("Hello world!" ...
- bzoj 3790 神奇项链 回文串 manacher|PAM
LINK:神奇项链 存在两个操作:1. 一个操作可以生成所有形式的回文串 2.一个操作可以将两个串给合并起来 如果前缀和后缀相同还可以将其并起来. 多组询问 每次询问合成一个串所需最少多少次2操作. ...
- linux的服务管理(centos6和Centos7)和网络管理(网卡配置),计划服务cron
服务和网络 管理 init ifcfg ens33 1.服务: Linux系统中提供的功能,统称为服务,如:at服务.cron服务.web服务.FTP服务.sshd服务等. 服务是由已经在运行的进程 ...
- python数据可视化编程实战PDF高清电子书
点击获取提取码:3l5m 内容简介 <Python数据可视化编程实战>是一本使用Python实现数据可视化编程的实战指南,介绍了如何使用Python最流行的库,通过60余种方法创建美观的数 ...
- 精通python网络爬虫PDF高清完整版免费下载|百度云盘|Python基础教程免费电子书
点击获取书籍提取码:yc9w
- DeepVO: Towards End-to-End Visual Odometry with Deep Recurrent Convolutional Neural Networks
1.Introduction DL解决VO问题:End-to-End VO with RCNN 2.Network structure a.CNN based Feature Extraction 论 ...
- SpringMvc异常处理和SpringMvc拦截器
1. 异常处理思路 Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherServlet找异常处理器进 行异常的处理. SpringMVC的异 ...