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

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

    微信公众号,相信不少人已经有接触,其开发分为许多种,本次主要说的是,通过微信认证后的公众号(下图,),使用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  

转载于:https://www.cnblogs.com/lekko/p/4288961.html

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值