上次写出来的《【Servlet】基于Jsp的微信Oauth2认证》(点击打开链接)相当地不好,浪费了许多页面,而且类的安排与布置非常地不明确,如果多个微信公众平台的程序需要调用到Oauth2认证,必须整段整段代码复制拷贝,这次,对其进行了改进,认证过程也封装到一个类里面,可以多次复用。
一、基本准备
首先,我们要到微信的开发者中心,修改“OAuth2.0网页授权”的接口,如下图:
这里的“授权回调页面域名”是应该填写你服务器的总域名,而不是下面的一个个工程名,比如我的服务器IP是192.168.0.1,域名是http://a.b.com,里面的微信工程是wechattest,你就应该填写192.168.0.1或者http://a.b.com,而不是192.168.0.1/wechattest,或者a.b.com/wechattest,这样即使通过了,后面也是无法进行微信Oauth认证的。
之后,才于eclipse写代码,与上次一样,我们要在java中解析json,因为微信送过来的信息都是json,而且我们用到Servlet,自然而然地需要在Eclipse中新建的工程的lib文件夹中放入如下两包:
二、基本思想
对于上次写出来的《【Servlet】基于Jsp的微信Oauth2认证》(点击打开链接)的思想,此次大幅度减少了jsp页面,甚至就把jsp页面的数目减到0,一切都在Servlet的java文件中进行,安全问题也得到了提升,但微信要求如何拿到用户信息,这里就不再赘述了,在上文已经说得比较详细了。
整个工程目录的布置如下:
其实这里最关键还是那个Oauth.java文件,这里Scanhandle.java是由于我拿到的用户信息之后,还要进行其它的操作,所以才命名成这个名字的。
三、制作过程
首先同样与上次一样,在Servlet的web.xml于<web-app>之间的写入你要跳转的链接,比如我要到wx.loginqrcode.Scanhandle这个类而且指明域名是/scanhandle进行Oauth认证,则与web.xml中写入:
<servlet> <servlet-name>scanhandle</servlet-name> <servlet-class>wx.loginqrcode.Scanhandle</servlet-class> </servlet> <servlet-mapping> <servlet-name>scanhandle</servlet-name> <url-pattern>/scanhandle</url-pattern> </servlet-mapping>
如果还不明白可以再参考我之前的《【Servlet】最简单的Servlet JavaWeb程序》(点击打开链接)
然后就是两个java文件:
1、Scanhandle.java
请忽略这个文件的命名~>_<!
package wx.loginqrcode; //首先由于oauth.java在其他的包里面,所以我们要引入这个包 import wx.oauth.*; //io异常需要 import java.io.*; //servlet需要 import javax.servlet.*; import javax.servlet.http.*; public class Scanhandle extends HttpServlet { //没有下面这句eclipse会出警告 private static final long serialVersionUID = 1L; //微信Oauth认证用到了get方法 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * @param code 这是微信提供的东西code * @param jsonstring 用户信息json字符串 */ String code = request.getParameter("code"); String jsonstring = null; //如果没有code,就向微信提供的网址请求 //state里面还可以带上你需要拿到用户信息之后进一步处理的参数 if (code == null) { /* * @param appid 微信提供给你的appid * @param redirect_uri 你自己的服务器地址/工程名/本页的Servelt名字 * @param state 你还需要带上的参数 */ response.sendRedirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=http://192.168.0.1/wechattest/scanhandle&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"); } else { //在后续需要进一步处理的参数,取出 String param = request.getParameter("state"); //向oauth.java拿到了用户信息之后,存到Session jsonstring = new Oauth().getUserinfo(code); request.getSession().setAttribute("jsonstring", jsonstring); //这里可以再写,你需要进一步处理的代码 } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
2、Oauth.java
这个文件就是《【Servlet】最简单的Servlet JavaWeb程序》(点击打开链接)一文的Loading.java被封装而已,具体的过程可以看上次那篇文章的流程图。由于微信Oauth2认证只是用到get方法,所以整个文件用到了《【Java】读取网页中的内容》(点击打开链接)的思想
package wx.oauth; import java.io.*; import java.net.*; import com.alibaba.fastjson.*; public class Oauth { public String getUserinfo(String code) throws IOException{ StringBuilder json = new StringBuilder(); String url = null; BufferedReader in = null; String inputLine = null; String jsonstring = null; JSONObject jobject = null; // 这里的appid与secret换成你自己的appid与secret url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=APPSECRET&code=" + code + "&grant_type=authorization_code"; in = new BufferedReader(new InputStreamReader(new URL(url) .openConnection().getInputStream(), "utf-8")); while ((inputLine = in.readLine()) != null) { json.append(inputLine); } in.close(); jsonstring = json.toString(); jobject = JSON.parseObject(jsonstring); json = new StringBuilder(); url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + jobject.getString("access_token") + "&openid=" + jobject.getString("openid"); in = new BufferedReader(new InputStreamReader(new URL(url) .openConnection().getInputStream(), "utf-8")); inputLine = null; while ((inputLine = in.readLine()) != null) { json.append(inputLine); } in.close(); jsonstring = json.toString(); return jsonstring; } }