微信公众号用户信息认证机制

又有一段时间没动笔了,确实工作后忙碌起来了,年末了,给大家拜年了,抽了这个空档把最近做的一个东西分享分享。

微信公众号,相信不少人已经有接触,其开发分为许多种,本次主要说的是,通过微信认证后的公众号(下图,),使用Oauth网页接口来获取用户信息的流程。

一、基础准备

首先,明确需求:有一个应用服务器,希望通过某个链接(菜单)进入此应用,在应用服务器端可以获得访问者的一些信息。

微信是不会直接让你在用户在访问应用服务器时直接取到用户信息的,而需要通过他们的专门的认证服务器来操作。作为开发者,目前有两类获取用户信息的方法,这里只介绍Oauth 2.0认证(其它还有一种CGI接口,是必须加了微信公众号关注后才可取到用户信息,而使用Oauth则可以不加关注也能取到),结合微信我整理了一个简单的流程:

1、用户点开了某个菜单或者链接,进入到了我们的后台应用服务器(原始请求:URL_ORG);

2、服务器发现没有用户认证信息(微信所谓的认证code,使用一次后失效),于是返回了一个rediret头给用户,并且让它去访问微信的认证服务器;

3、用户的浏览器会去访问微信的认证服务器(用户会看到闪一下,这是重定向进行中);

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=URL_ORG&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect

4、如果用户授权(微信会询问,是否授权,如果加了关注的用户则不会询问,默认授权),则微信认证服务器会返回一个redirect头给用户,同时包含了认证code,让用户浏览器去访问原始请求的链接;

5、这时用户的浏览器会带着code去访问我们的后台应用(此时还会再闪一下,重定向:URL_ORG?code=xxxxxx);

6、应用服务器拿到了code还没有用,还得由应用服务器去向微信认证服务器取token(ACCESS_TOKEN,一段时间内有效),在取得token时还会返回用户的openId(OEPNID);

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

7、在取到token、openId后,再发起一次请求,取得用户的个人信息;

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

上面的过程,看起来非常复杂, 没错,有两次重定向!但是好处在于,用户访问的原始链接肯定是干净的,比如www.abc.com/xxx,微信那边的链接或菜单在设置时不需要变动。如果大家愿意去维护菜单的链接地址,也可以使用微信官方文档的方法,省去上面的第1、2步,直接把原始链接设置为:微信认证接口地址+待回调原始地址,的模式,减少一次用户可感知的闪烁。

二、核心代码

转java后,我也没时间去写成其它语言了,大家就看java代码吧,第一个地方,对应用服务器需求使用用户信息的url地址使用filter:

 1 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
 2         HttpServletRequest request = (HttpServletRequest) servletRequest;
 3         HttpServletResponse response = (HttpServletResponse) servletResponse;
 4         HttpSession session = request.getSession();
 5         if (request != null) {
 6                 // 尝试公众号
 7                 Object openId = session.getAttribute(WxSession.WX_OPENID_KEY);
 8                 // 未完成认证
 9                 if (openId == null) {
10                     String code = request.getParameter("code");
11                     if (code != null) {
12                         // 第二步,通过code换取access_token和OpenId
13                         JSONObject ret = _authService.getAccessToken(code);
14                         String token = ret.getString("access_token");
15                         openId = ret.getString("openid");
16                         // 第三步,拉取用户信息
17                         ret = _authService.getExternalUserInfo(token, openId.toString());
18                         String nickname = ret.getString("nickname");
19                         // 存session
20                         session.setAttribute(WxSession.WX_OPENID_KEY, openId);
21                         session.setAttribute(WxSession.WX_USER_NAME_KEY, nickname);
22                     } else {
23                         // 第一步,获取code
24                         response.sendRedirect(_authService.getExternalAuthUrl(request.getRequestURL().toString()));
25                         return;
26                     }
27                 }
28         }
29         filterChain.doFilter(servletRequest, servletResponse);
30     }

上面的代码有注释,非常明白了,先看有没有code,没有code就重定向去取,取到后用户再来;当有code时,服务器自己去取token和openid,取到后再取任何用户信息(上面只取了用户昵称)。

第二个地方,上面代码中的getExternalAuthUrl、getAccessToken、getExternalUserInfo三个方法:

 1 /**
 2      * 跳转到OAuth登录页面,可有用户的详细信息
 3      */
 4     public String getExternalAuthUrl(String redirectUri) {
 5         String encodeUrl = null;
 6         try {
 7             encodeUrl = URLEncoder.encode(redirectUri, "UTF-8");
 8         } catch (UnsupportedEncodingException e) {
 9             _log.error(e);
10         }
11         String url = "https://open.weixin.qq.com/connect/oauth2/authorize";
12         url += "?appid=" + Constant.Subscribe.AppId;
13         url += "&redirect_uri=" + encodeUrl;
14         url += "&response_type=code";
15         url += "&scope=snsapi_userinfo";
16         url += "&state=123";
17         url += "#wechat_redirect";
18         return url;
19     }
20
21         /**
22      * 获取OAuth的access_token,错误时返回null
23      */
24     public JSONObject getAccessToken(String code) {
25         String url = "https://api.weixin.qq.com/sns/oauth2/access_token";
26         url += "?appid=" + Constant.Subscribe.AppId;
27         url += "&secret=" + Constant.Subscribe.AppSecret;
28         url += "&code=" + code;
29         url += "&grant_type=authorization_code";
30         try {
31             String responseStr = HttpInvork.getRequestWithoutHeader(url);
32             JSONObject json = JSONObject.fromObject(responseStr);
33             String access_token = json.getString("access_token");
34             if (StringUtils.isNotEmpty(access_token)) {
35                 return json;
36             }
37         } catch (Exception e) {
38             _log.error(e);
39         }
40         return null;
41     }
42
43     /**
44      * 获取OAuth微信用户信息,错误时返回null
45      */
46     public JSONObject getExternalUserInfo(String accessToken, String openId) {
47         String url = "https://api.weixin.qq.com/sns/userinfo";
48         url += "?access_token=" + accessToken;
49         url += "&openid=" + openId;
50         url += "&lang=zh_CN";
51         String responseStr = HttpInvork.getRequestWithoutHeader(url);
52         try {
53             return JSONObject.fromObject(responseStr);
54         } catch (Exception e) {
55             _log.error(e);
56         }
57         return null;
58     }

第三个地方,上面的HttpInvork.getRequestWithoutHeader方法,我就不贴了,大家随便写/找个可以发送get请求的方法代替一下吧。

三、福利?

大家不满足于Oauth?那我把CGI代码也贴出来吧。先还是说明一下:使用cgi方式时,openid还是跟前面的类似,scope可改为snsapi_base(不改也无所谓啦,还有一种openid获取方法前面没有说,就是向公众号发了消息,然后通过微信的公众平台的服务器配置绑定到了后台应用,通过解析后也可以取到openid),然后还是要token才能要用户信息,只是这里就不能用Oauth的token了,而是普通的cgi token,代码:

 1 /**
 2      * 获取CGI的access_token,错误时返回null
 3      */
 4     public String getCgiAccessToken() {
 5         String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
 6         url += "&appid=" + Constant.Subscribe.AppId;
 7         url += "&secret=" + Constant.Subscribe.AppSecret;
 8         try {
 9             String responseStr = HttpInvork.getRequestWithoutHeader(url);
10             JSONObject json = JSONObject.fromObject(responseStr);
11             String access_token = json.getString("access_token");
12             if (StringUtils.isNotEmpty(access_token)) {
13                 return access_token;
14             }
15         } catch (Exception e) {
16             _log.error(e);
17         }
18         return null;
19     }
20
21     /**
22      * 通过CGI获取微信用户信息,错误时返回null
23      */
24     public JSONObject getCgiUserInfo(String accessToken, String openId) {
25         String url = "https://api.weixin.qq.com/cgi-bin/user/info";
26         url += "?access_token=" + accessToken;
27         url += "&openid=" + openId;
28         url += "&lang=zh_CN";
29         String responseStr = HttpInvork.getRequestWithoutHeader(url);
30         try {
31             return JSONObject.fromObject(responseStr);
32         } catch (Exception e) {
33             _log.error(e);
34         }
35         return null;
36     }

说了好多,我建议是,大家申请一个实战演练演练,除了认证复杂了点,其它开发跟传统的web开发没啥太大区别了,微信JS-SDK都给你准备好了。过年快乐!

转载请注明原址:http://www.cnblogs.com/lekko/p/4288961.html

时间: 2024-10-08 17:59:55

微信公众号用户信息认证机制的相关文章

微信公众号用户与网站用户的绑定(一)

绑定:对于同一个用户,我们如何建立微信公众号用户(openid)与网站用户(userid)之间的对应关系. 一次完整的绑定流程应该是这样的: ①用户登录网页,点击"绑定微信账户":②后台使用微信接口,生成二维码链接返回给前端显示,并建立场景值A与用户的对应关系:③用户扫描二维码,并点击关注微信公众号(假如已关注,直接跳到④):④后台接收微信服务器推送的场景值A:⑤后台根据场景值A,查询到对应的用户ID(依赖于②中建立的对应关系):⑥建立用户userid与微信用户openid的对应关系:

微信公众号用户与网站用户的绑定方案

现在很多网站都已经建立了一套完整的用户账号体系,基于这套体系,再做其他应用的用户扩展就非常方便.例如,有了微软的outlook账户,就可以登录win8,可以登录微软的邮箱,还可以登录skype.同样地,一个Apple ID可以享受苹果的所有服务.正所谓,一个账号,处处使用.对于企业,可能会有产品线通常有网站,app,微信公众号等.统一各产品线的账号体系,实现一个账号处处使用的目标是非常有必要的.网站和app使用同一个账号,不需要做任何多余的工作,客户只要有用户名密码即可登录.对于微信公众号,由于

asp获取微信公众号用户的头像和微信名及openid源码

asp获取微信公众号用户的头像和微信名及openid源码,asp写的,可以获取用户的头像和微信名,性别及openid等 <script language="jscript" runat="server">function getjson(str){ try{ eval("var jsonStr = (" + str + ")"); }catch(ex){ var jsonStr = null; } return j

使用Django实现微信公众号用户openid登录认证

最近在用Django做一个小项目,需要将微信的用户与网站的用户进行关联,由于是微信的订阅号,没有oauth网页授权的权限,只能退而求其次,在响应中获取用户的openid,来唯一的标识用户. Django中用户的模型继承和扩展于AbstractUser,在用户模型中添加openid字段: models.py class Users(AbstractUser): openid = models.CharField(max_length=100,blank=True,null=True,verbose

微信公众号用户与网站用户的绑定-登陆公众号时获取openid(二)

如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑. 关于网页授权回调域名的说明 1.在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的开发者中心页配置授权回调域名.请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加http://等协议头: 2.授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html . ht

作业七——“南通大学教务管理系统微信公众号” 用户体验分析

1. 目标 基于实例分析,体会用户体验设计的 7 条准则 2. 要求 基于我们列出的 7 条UX评价准则,分析“南通大学教务管理系统微信公众号” 在用户体验设计方面让你觉得满意的地方(不少于2点):(20分),请陈述理由. 同样,分析“南通大学教务管理系统微信公众号” 在用户体验设计方面让你觉得最不满意的地方(不少于2点):(20分),请陈述理由. 回答上述问题时,附上截图 使用Nielsen的十条准则做WEB的启发式评估 基于以下设计准则去做评估: Visibility of system s

Python 抓取微信公众号账号信息

搜狗微信搜索提供两种类型的关键词搜索,一种是搜索公众号文章内容,另一种是直接搜索微信公众号.通过微信公众号搜索可以获取公众号的基本信息及最近发布的10条文章,今天来抓取一下微信公众号的账号信息( 爬虫 首先通过首页进入,可以按照类别抓取,通过"查看更多"可以找出页面链接规则: import requests as req import re reTypes = r'id="pc_\d*" uigs="(pc_\d*)">([\s\S]*?)

《转之微信移动团队微信公众号》iOS 事件处理机制与图像渲染过程

致歉声明: Peter在开发公众号功能时触发了一个bug,导致群发错误.对此我们深表歉意,并果断开除了Peter.以下交回给正文时间: iOS 事件处理机制与图像渲染过程 iOS RunLoop都干了什么 iOS 为什么必须在主线程中操作UI 事件响应 CALayer CADisplayLink 和 NSTimer iOS 渲染过程 渲染时机 CPU 和 GPU渲染 Core Animation Facebook Pop介绍 AsyncDisplay介绍 参考文章 iOS RunLoop都干了什

作业七—“南通大学教务管理系统微信公众号”用户体验分析

 这次分析其实更像是用户的使用报告和反馈.当然,如果所提建议能被公众号维护者所考虑,那也是特别让人(用户)感到兴奋的.      基于Nielsen十条设计准则: Visibility of system status.可视性原则 Match between system and real world.不要脱离现实 User control and freedom.用户有自由控制权 Consistency.一致性原则 Error strategy.有预防用户出错的措施 Recognition r