引言

用户登陆时,原设计是使用工号加密码进行登陆,只是工号不好记,为了推广,设计了企业微信登陆。

企业微信中可以设置自建应用,其实就是内嵌了一个Chrome,点击左侧的自建应用,会在右侧浏览器显示相关应用,所有工作都放在企业微信中,需实现当前企业微信账号自动登陆系统。

开发的过程很坎坷。让微信折腾的一点脾气都没有。

当时不会调试,因为企业微信中的自建应用要求设置成线上地址,写好了,打包,传给服务器,然后再测试。

五点,觉得还有十分钟就写完了,写完了就去吃饭。

六点、八点,改到九点半,都要改哭了,还是不好使,最后放弃了。

后来邢彦年师兄帮我梳理流程,潘老师教我调试方法,才完成这个功能。

感谢邢彦年师兄和潘老师。

实现

文档

找文档一定要找对地方,两个API,一个服务端,一个客户端。

最开始我以为是使用客户端的API呢?点进去学了学,企业微信小程序可用的API接口,这个用不了,此应用不是小程序。然后JS-SDK不支持登陆授权。

相关文档在服务端API中的身份认证一节中。

OAuth 2.0

当我们用微信登陆某个网站时,会出现类似这样的授权页面。

点击确认登陆,该应用就能获取到用户相关的信息。

用户通过用户名和密码的方式进行微信的使用,第三方应用想获取微信用户信息,不是通过用户名密码,而是微信提供的令牌,这就是OAuth 2.0,既可以让应用获取不敏感的信息,又可以保证账户的安全性。

登陆流程

用户点开应用,实际上是访问当前系统微信授权的入口

微信网页授权地址:https://open.weixin.qq.com/connect/oauth2/authorize

参数

说明

appid

企业的CorpID

redirect_uri

授权后的回调地址,需使用urlencode处理

response_type

回调数据返回类型

scope

应用授权作用域。企业自建应用固定填写:snsapi_base

state

回调时额外的参数,非必选

#wechat_redirect

终端使用此参数判断是否需要带上身份信息

看这个表格也是在无聊,下面是我配置好的微信授权链接,大家只需将相应参数改写即可。注:回调的url一定要使用encodeURIComponent处理!

https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxxxxxxx&redirect_uri=https%3A%2F%2Falice.dgitc.net%2Fsetup%2Fwechat&response_type=code&scope=snsapi_base#wechat_redirect

用户静默授权成功,跳转到回调地址

用户授权成功后,会带着code参数重定向到回调地址。

类似这样:

https://alice.dgitc.net/setup/wechat?code=xxxxxx

前台的组件就通过路由获取到了code,然后通过code去进一步获取用户信息。

const code = this.route.snapshot.queryParamMap.get('code');

this.userService.enterpriseWeChatLogin(code).subscribe(...);

后台通过code找微信后台获取用户信息

这个是分成两次获取,先获取access_token,再通过access_token和code获取用户信息。

GET请求 https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET

这个是获取access_token的地址,获取access_token的过程是重点!

上面传的参数名是corpid和corpsecret,企业id和密钥。

这是企业微信的设计,企业id是一个,标识这个企业,每一个功能模块都有相应的secret。

然后企业id和secret配对,获取到只能访问这个功能模块的一个access_token。

就拿当前Alice系统来举例,自建应用Alice存在secret,通过此secret和corpid获取到access_token,即相当于拿到了受保护API的访问权限。

因为这个access_token是通过Alice应用的secret获取到的,所以再用它访问其他的功能,是不合法的。

access_token有访问频率限制,所以设计了一套缓存方案。

@Override

public String getAccessTokenBySecret(String secret) {

logger.debug("从缓存中获取令牌");

String access_token = this.cacheService.get(secret);

logger.debug("如果获取到了,直接返回");

if (null != access_token) {

return access_token;

}

logger.debug("否则,发起HTTP请求");

logger.debug("获取企业验证信息");

String url = enterpriseInformation.getAccessTokenUrl();

String corpId = enterpriseInformation.getCorpid();

logger.debug("获取认证令牌");

ResponseEntity responseEntity = restTemplate.getForEntity(url + "?corpid=" + corpId + "&corpsecret=" + secret, EnterpriseAuth.class);

logger.debug("如果请求成功");

if (responseEntity.getStatusCode().is2xxSuccessful()) {

logger.debug("获取响应体");

EnterpriseAuth enterpriseAuth = responseEntity.getBody();

Assert.notNull(enterpriseAuth, "微信令牌为空");

logger.debug("如果微信请求成功");

if (enterpriseAuth.successed()) {

logger.debug("存储缓存,返回令牌");

access_token = enterpriseAuth.getAccessToken();

this.cacheService.put(secret, access_token, enterpriseAuth.getExpiresIn(), TimeUnit.SECONDS);

return access_token;

}

}

logger.debug("请求失败,返回空令牌");

return "";

}

缓存是通过把Redis工具类包装了一下实现的,很简单。

@Service

public class CacheServiceImpl implements CacheService {

/**

* Redis操作模版

*/

private final StringRedisTemplate redisTemplate;

private final ValueOperations valueOperations;

@Autowired

public CacheServiceImpl(StringRedisTemplate redisTemplate) {

this.redisTemplate = redisTemplate;

this.valueOperations = redisTemplate.opsForValue();

}

@Override

public void put(String key, String value, Long time, TimeUnit timeUnit) {

this.valueOperations.set(key, value, time, timeUnit);

}

@Override

public String get(String key) {

return this.valueOperations.get(key);

}

@Override

public void clear(String key) {

this.redisTemplate.delete(key);

}

}

access_token和code都有了,终于可以获得用户信息了。

GET请求 https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE

这个简单了,问题出在数据不规范的问题上,大写的json,如果按这样建,实体就不符合java规范了。

{

"errcode": 0,

"errmsg": "ok",

"UserId":"USERID",

"DeviceId":"DEVICEID"

}

最后在字段添加JsonAlias注解。

@JsonAlias("UserId")

private String userId;

这里获取到的信息是用户的userId,这个userId和我们熟知的openId是不一样的。

userId就是管理员为用户在企业内设置的唯一标识,企业内唯一。

具体的后台获取userId的细节:

@Override

public Boolean enterpriseWeChatLogin(String code) {

logger.debug("构造参数");

String secret = this.enterpriseInformation.getAgentSecret();

String access_token = this.aliceCommonService.getAccessTokenBySecret(secret);

String url = this.enterpriseInformation.getUserInfoUrl() + "?code=" + code + "&access_token=" + access_token;

logger.debug("请求用户信息");

ResponseEntity responseEntity = this.restTemplate.getForEntity(url, EnterpriseUser.class);

logger.debug("如果请求成功");

if (responseEntity.getStatusCode().is2xxSuccessful()) {

logger.debug("获取响应体");

EnterpriseUser enterpriseUser = responseEntity.getBody();

Assert.notNull(enterpriseUser, "企业用户不能为空");

logger.debug("如果企业微信端也成功了");

if (enterpriseUser.successed()) {

logger.debug("获取userId");

String wxId = enterpriseUser.getUserId();

logger.debug("如果有userId,说明当前用户存在此企业中");

if (null != wxId) {

// 请自行填充登陆的具体细节

}

} else if (enterpriseUser.tokenInvalided()) {

logger.debug("token不合法,清空缓存,重新获取");

this.cacheService.clear(secret);

return this.enterpriseWeChatLogin(code);

}

}

logger.debug("其他一律返回false");

return false;

}

前台跳转,登陆成功

前台在订阅中添加跳转方法,登陆成功后,跳转到首页,登陆失败,401走拦截器,跳转到登陆页。

this.userService.enterpriseWeChatLogin(code)

.subscribe(() => {

this.userService.setCurrentLoginUser();

this.router.navigateByUrl('main');

}, () => {

console.log('network error');

});

改Host

一定要记住,非常重要!!!

以后再碰到只能访问线上地址的情况,想在本地调试,一定要改Host!!!

总结

最后的总结就是多想想潘老师评论的这句话,有些路总不过去,很大的可能是方法错了。

企业微信oauth认证_企业微信登陆相关推荐

  1. 企业微信oauth认证_微信企业号OAuth2验证接口实例(使用SpringMVC)

    企业应用中的URL链接(包含自己定义菜单或者消息中的链接).能够通过OAuth2.0来获取员工的身份信息. 注意.此URL的域名,必须全然匹配企业应用设置项中的'可信域名'.否则获取用户信息时会返回5 ...

  2. 企业信用等级AAA认证 山东企业信用3A认证办理费用周期

    企业信用等级AAA认证 山东企业信用3A认证办理费用周期 企业信用等级AAA认证 山东企业信用3A认证办理费用周期 企业信用等级AAA证书,资信等级3A认证,重合同守信用企业.诚信企业家证书 八证一铜 ...

  3. 微信收款接口_企业微信:3.0.26版本新功能介绍

    一.客户联系功能增强 对外收款 员工可以在聊天中直接向微信用户收款了,收款时还可要求顾客填写联系信息方便邮寄.所收款项进入企业的微信支付商户号由企业统一管理,企业还可查看每个员工的收款业绩明细. 其他 ...

  4. 你有一条微信未发送_企业微信及虎赞SCRM常见问题整理

    本期问题汇总: ● 为何点击企业微信聊天工具栏,显示"未授权"? ● 在企业微信聊天工具栏,如何添加和删除应用? ● 使用企业微信发送朋友圈,为何显示没有可发送的客户? ● 虎赞S ...

  5. 如何自建微信外卖平台_打造微信外卖平台,就是这么简单!

    目前,外卖平台已经发展并且出于饱和状态,美团.饿了么各站市场的半壁江山.大城市中,我们无法与其正面抗衡,但是在三.四线小县城就可以!由于小县城外卖行业竞争较小.利润空间大,对于想从事外卖平台的创业者来 ...

  6. Spring Boot+微信小程序_保存微信登录者的个人信息

    1. 前言 微信小程序开发平台,提供有一类 API,可以让开发者获取到微信登录用户的个人数据.这类 API 统称为开放接口. Tip:微信小程序开发平台,会把微信登录用户的个人信息分为明文数据和敏感数 ...

  7. 忘了微信密码怎么办_忘记微信密码了怎么办,一招帮你快速找回密码

    微信的使用几乎成为了一种生活不可或缺的生活方式.如果我们在不经意间忘记了这个微信登陆密码该怎么办?如何找回呢? 根据微信注册的方式,找回帐号大致分为以下三类: 第一种,以QQ号注册的微信帐号 如果你的 ...

  8. python 自动化微信小程序_干货 | 微信小程序自动化测试最佳实践(附 Python 源码)...

    原标题:干货 | 微信小程序自动化测试最佳实践(附 Python 源码) 本文为霍格沃兹测试学院测试大咖公开课<微信小程序自动化测试>图文整理精华版. 随着微信小程序的功能和生态日益完善, ...

  9. 历史 微信开发者工具_不用微信开发者工具也能调试微信页面

    一般调试微信页面的时候,我们都会按照微信开发的官网教程,让你去安装微信开发者工具,然后在微信开发者工具上调试, 这样有时候会不会感觉很麻烦? 而且这个工具还经常卡死. 1515737321133.jp ...

  10. 企业破产重整网_企业破产重整的基本流程是怎样的?

    一.企业破产重整的基本流程是怎样的? 按照新破产法的规定,重整程序的申请人分为两种情况: (1)破产案件受理前的初始重整申请,可以由债务人或者债权人提出. (2)破产案件受理后,破产宣告前的后续重整申 ...

最新文章

  1. H3C 交换机命名规则
  2. python中string.digits_python学习笔记五:字符串方法
  3. $Django 中间件 csrf
  4. jQuery EasyUI API 中文文档 - Documentation 文档
  5. Jquery学习笔记:删除节点的操作
  6. BZOJ5251:[九省联考2018]劈配——题解
  7. shell 脚本中 while 只执行一次
  8. Visual Studio 2008 每日提示(一)
  9. 测试监控系列:使用vb批量统计nmon结果
  10. VS2010提示asp.net v4.0 尚未在web服务器上注册
  11. 华为前线核心组织“铁三角”是如何运作的?营销LTC变革与“铁三角”啥关系?--LTC专家许浩明老师分享
  12. 【Pycharm】解决Debug模式下出现collecting data问题
  13. 如何从巨潮资讯爬取股票公告
  14. 2022-07-17 第四小组 孙翰章 职业规划
  15. w10共享网络没有计算机,win10网络共享找不到对方电脑怎么办
  16. 一文搞懂K-means聚类算法
  17. 不用代码免费采集网站内容_看一遍就能上手的火车头采集图文全流程教程
  18. 3个月周末,软考高级复习攻略,信息系统项目管理师考后总结
  19. 记录一次vue项目引入GoogleMap API进行地图定位
  20. 学Linux有哪些就业方向?

热门文章

  1. 线上幽灵:世界头号黑客米特尼克自传
  2. win10动态桌面软件
  3. HMC5883L 电子指南针用树莓派进行磁场干扰过滤 校准
  4. java speex转码_微信Speex转wav,Speex to wav
  5. 思科模拟配置文件服务器,思科模拟服务器配置教程
  6. Elasticsearch docker中搭建ES服务集群,ik中文分词器,使用Kibana操作ES 搜索 spring Data Elasticsearch-增删改查API
  7. CGAL库的安装及示例代码的编译
  8. 固态激光雷达:扫地机器人的旋转激光雷达的三角测距示意原理与分析
  9. Sublime Text 3.0安装及破解汉化
  10. HTTP性能测试工具siege