6.3.4 案例:通过网页授权获取用户信息
为了让读者进一步理解并掌握网页授权流程及其实现,下面来看一个演示案例。
1.编写授权回调请求处理程序
如果要在网页中得到用户信息,就必须先引导用户进入网页授权页面;用户同意授权后会跳转到回调地址redirect_uri,redirect_uri是授权回调请求处理程序的访问地址;在处理程序中,开发者能够获取到code,再通过code获取access_token,最终得到用户信息。
授权回调请求处理程序的实现如下:
- 1 package org.liufeng.course.servlet;
- 2 import java.io.IOException;
- 3 import javax.servlet.ServletException;
- 4 import javax.servlet.http.HttpServlet;
- 5 import javax.servlet.http.HttpServletRequest;
- 6 import javax.servlet.http.HttpServletResponse;
- 7 import org.liufeng.course.pojo.SNSUserInfo;
- 8 import org.liufeng.course.pojo.WeixinOauth2Token;
- 9 import org.liufeng.course.util.AdvancedUtil;
- 10
- 11 /**
- 12 * 授权后的回调请求处理
- 13 *
- 14 * @author liufeng
- 15 * @date 2013-11-12
- 16 */
- 17 public class OAuthServlet extends HttpServlet {
- 18 private static final long serialVersionUID = -1847238807216447030L;
- 19
- 20 public void doGet(HttpServletRequest request, HttpServletResponse response)
- 21 throws ServletException, IOException {
- 22 request.setCharacterEncoding("gb2312");
- 23 response.setCharacterEncoding("gb2312");
- 24
- 25 // 用户同意授权后,能获取到code
- 26 String code = request.getParameter("code");
- 27
- 28 // 用户同意授权
- 29 if (!"authdeny".equals(code)) {
- 30 // 获取网页授权access_token
- 31 WeixinOauth2Token weixinOauth2Token =
- AdvancedUtil.getOauth2A ccessToken("APPID", "APPSECRET", code);
- 32 // 网页授权接口访问凭证
- 33 String accessToken = weixinOauth2Token.getAccessToken();
- 34 // 用户标识
- 35 String openId = weixinOauth2Token.getOpenId();
- 36 // 获取用户信息
- 37 SNSUserInfo snsUserInfo = AdvancedUtil.getSNSUserInfo(accessToken,
- openId);
- 38
- 39 // 设置要传递的参数
- 40 request.setAttribute("snsUserInfo", snsUserInfo);
- 41 }
- 42 // 跳转到index.jsp
- 43 request.getRequestDispatcher("index.jsp").forward(request, response);
- 44 }
- 45 }
上代码是通过Servlet接收和处理授权回调请求,由于授权完成后是通过URL传递code参数,只需要在doGet()方法中进行处理即可。
第26行代码用于获取code参数。
第29行是根据code判断用户是否同意授权,如果code等于"authdeny"表示用户不同意授权,否则表示同意授权。如果用户不同意授权,则直接跳转到目标页面;如果用户同意授权,则可以调用已经封装好的方法获取用户信息。
第31行是根据APPID、APPSECRET和code获取网页授权access_token,同时也能获取到用户的OpenID。
第37行是获取用户信息。
第40行代码是将用户信息放到request对象中,这样可以传递到目标页面。如果网页授权作用域为snsapi_base,则不能获取用户信息,只需将OpenID放到request对象中即可。最后,通过第43行代码跳转到目标页面。
接下来,需要在项目的web.xml中增加关于OAuthServlet类的配置,代码如下:
- <servlet>
- <servlet-name>oauthServlet</servlet-name>
- <servlet-class>
- org.liufeng.course.servlet.OAuthServlet
- </servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>oauthServlet</servlet-name>
- <url-pattern>/oauthServlet</url-pattern>
- </servlet-mapping>
2.编写目标页面
用户授权完成后,会通过redirect_uri跳转到目标页面index.jsp,该页面的代码如下:
- 1 <%@ page language="java" pageEncoding="gb2312"%>
- 2 <%@ page import="org.liufeng.course.pojo.SNSUserInfo;"%>
- 3 <html>
- 4 <head>
- 5 <title>OAuth2.0网页授权</title>
- 6 <meta name="viewport" content="width=device-width,user-scalable=0">
- 7 <style type="text/css">
- 8 *{margin:0; padding:0}
- 9 table{border:1px dashed #B9B9DD;font-size:12pt}
- 10 td{border:1px dashed #B9B9DD;word-break:break-all; word-wrap:break-word;}
- 11 </style>
- 12 </head>
- 13 <body>
- 14 <%
- 15 // 获取由OAuthServlet传入的参数
- 16 SNSUserInfo user = (SNSUserInfo)request.getAttribute("snsUserInfo");
- 17 if(null != user) {
- 18 %>
- 19 <table width="100%" cellspacing="0" cellpadding="0">
- 20 <tr><td width="20%">属性</td><td width="80%">值</td></tr>
- 21 <tr><td>OpenID</td><td><%=user.getOpenId()%></td></tr>
- 22 <tr><td>昵称</td><td><%=user.getNickname()%></td></tr>
- 23 <tr><td>性别</td><td><%=user.getSex()%></td></tr>
- 24 <tr><td>国家</td><td><%=user.getCountry()%></td></tr>
- 25 <tr><td>省份</td><td><%=user.getProvince()%></td></tr>
- 26 <tr><td>城市</td><td><%=user.getCity()%></td></tr>
- 27 <tr><td>头像</td><td><%=user.getHeadImgUrl()%></td></tr>
- 28 <tr><td>特权</td><td><%=user.getPrivilegeList()%></td></tr>
- 29 </table>
- 30 <%
- 31 }
- 32 else
- 33 out.print("未获取到用户信息!");
- 34 %>
- 35 </body>
- 36 </html>
上述目标页面的实现比较简单,只是简单展示了当前用户的详细信息。第6行的meta标签用于设置网页的宽度以及是否可缩放,这样页面就能自适应各种大小屏幕的手机。如果不进行此项设置,则页面显示在手机上会非常小,不方便查看。"width=device-width"是将网页宽度设置为手机屏幕的宽度,“user-scalable=0”是禁止用户手动缩放。第16~28行的作用是将获取到的用户信息显示在页面上。
3.构造网页授权链接
在6.3.2节曾介绍过网页授权相关内容,网页授权链接的格式如下:
- https:// open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=
- REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
我们要根据实际情况替换链接中的APPID、REDIRECT_URI和SCOPE。相信读者对APPID和SCOPE已经非常熟悉了,这里需要注意的是REDIRECT_URI,它表示授权回调地址(OAuthServlet的访问地址),但是要进行URL编码。假如项目部署到BAE上以后,OAuthServlet的访问地址如下:
- http:// 0.weixinmptest.duapp.com/oauthServlet
则对上述地址进行URL编码得到的结果就是REDIRECT_URI的值,URL编码方法如下:
- /**
- * URL编码(utf-8)
- *
- * @param source
- * @return
- */
- public static String urlEncodeUTF8(String source) {
- String result = source;
- try {
- result = java.net.URLEncoder.encode(source, "utf-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return result;
- }
- String oauthUrl = "http:// 0.weixinmptest.duapp.com/oauthServlet"
- System.out.println(urlEncodeUTF8(oauthUrl));
编码后的结果如下:
- http%3A%2F%2F0.weixinmptest.duapp.com%2FoauthServlet
最终得到的网页授权链接如下:
- https:// open.weixin.qq.com/connect/oauth2/authorize?appid=wx9fd67526e31e66bb&redirect_uri=
- http%3A%2F%2F0.weixinmptest.duapp.com%2FoauthServlet
- &response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
在公众账号中,可以通过文本消息、图文消息或view菜单按钮将网页授权链接提供给用户。对于view菜单按钮,只需要将它的url属性值设置成上面的链接即可,用户点击菜单后就会进入到网页授权界面。
4.测试体验
为了演示方便,笔者直接将网页授权链接以文本消息的形式提供给用户,完整案例的演示结果如图6-5所示。
图6-5 通过OAuth2.0网页授权获取用户信息演示