Java实现微信网页授权的示例代码
开发前的准备:
1、需要有一个公众号(我这里用的测试号),拿到appid和appsecret;
2、进入公众号开发者中心页配置授权回调域名。具体位置:接口权限-网页服务-网页账号-网页授权获取用户基本信息-修改
注意,这里仅需填写全域名(如www.qq.com、www.baidu.com),勿加 http:// 等协议头及具体的地址字段;
我们可以通过使用ngrok来虚拟一个域名映射到本地开发环境,网址https://www.ngrok.cc/,大家自己去下载学习怎么使用
同时还需要扫一下这个二维码
授权步骤:
1、引导用户进入授权页面同意授权,获取code
2、通过code换取网页授权access_token(与基础支持中的access_token不同)
3、通过网页授权access_token和openid获取用户基本信息
先看一下我的项目结构:
web.xml相关代码:
<?xml version="1.0" encoding="utf-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="webapp_id" version="3.0"> <display-name>wxauth</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>wxcallback</servlet-name> <servlet-class>com.xingshang.servlet.callbackserclet</servlet-class> <init-param> <param-name>dburl</param-name> <param-value>jdbc:mysql://127.0.0.1:3306/wxauth</param-value> </init-param> <init-param> <param-name>driverclassname</param-name> <param-value>com.mysql.jdbc.driver</param-value> </init-param> <init-param> <param-name>username</param-name> <param-value>root</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>123456</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>wxcallback</servlet-name> <url-pattern>/wxcallback</url-pattern> </servlet-mapping> </web-app>
authutil工具类:
package com.xingshang.util; import java.io.ioexception; import org.apache.http.httpentity; import org.apache.http.httpresponse; import org.apache.http.client.clientprotocolexception; import org.apache.http.client.methods.httpget; import org.apache.http.impl.client.defaulthttpclient; import org.apache.http.util.entityutils; import net.sf.json.jsonobject; public class authutil { public static final string appid = "wx45c1428e5584fcdb"; public static final string appsecret = "98174450eb706ada330f37e646be85d5"; public static jsonobject dogetjson(string url) throws clientprotocolexception, ioexception{ jsonobject jsonobject = null; //首先初始化httpclient对象 defaulthttpclient client = new defaulthttpclient(); //通过get方式进行提交 httpget httpget = new httpget(url); //通过httpclient的execute方法进行发送请求 httpresponse response = client.execute(httpget); //从response里面拿自己想要的结果 httpentity entity = response.getentity(); if(entity != null){ string result = entityutils.tostring(entity,"utf-8"); jsonobject = jsonobject.fromobject(result); } //把链接释放掉 httpget.releaseconnection(); return jsonobject; } }
java实现:
1、引导用户进入授权页面同意授权,获取code
这一步其实就是将需要授权的页面url拼接到微信的认证请求接口里面,比如需要用户在访问页面 时进行授权认证
其中的scope参数有两个值:
snsapi_base:只能获取到用户openid。好处是静默认证,无需用户手动点击认证按钮,感觉上像是直接进入网站一样。
snsapi_userinfo:可以获取到openid、昵称、头像、所在地等信息。需要用户手动点击认证按钮。
相关代码
package com.xingshang.servlet; import java.io.ioexception; import java.net.urlencoder; import javax.servlet.servletexception; import javax.servlet.annotation.webservlet; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import com.xingshang.util.authutil; /** * 入口地址 * @author administrator * */ @webservlet("/wxlogin") public class loginservlet extends httpservlet { /** * */ private static final long serialversionuid = 1l; @override protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { //第一步:引导用户进入授权页面同意授权,获取code //回调地址 // string backurl = "http://suliu.free.ngrok.cc/wxauth/callback"; //第1种情况使用 string backurl = "http://suliu.free.ngrok.cc/wxauth/wxcallback";//第2种情况使用,这里是web.xml中的路径 //授权页面地址 string url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+authutil.appid + "&redirect_uri="+urlencoder.encode(backurl) + "&response_type=code" + "&scope=snsapi_userinfo" + "&state=state#wechat_redirect"; //重定向到授权页面 response.sendredirect(url); } }
2、通过第一步获取的code换取网页授权access_token(与基础支持中的access_token不同)
这一步需要在控制器中获取微信回传给我们的code,通过这个code来请求access_token,通过access_token和openid获取用户基本信息:
相关代码:
package com.xingshang.servlet; import java.io.ioexception; import java.sql.connection; import java.sql.drivermanager; import java.sql.preparedstatement; import java.sql.resultset; import java.sql.sqlexception; import javax.servlet.servletconfig; import javax.servlet.servletexception; import javax.servlet.annotation.webservlet; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import com.xingshang.util.authutil; import net.sf.json.jsonobject; /** * 回调地址 * @author administrator * */ //@webservlet("/callback") public class callbackserclet extends httpservlet { /** * */ private static final long serialversionuid = 1l; private string dburl; private string driverclassname; private string username; private string password; private connection conn =null; private preparedstatement ps =null; private resultset rs = null; //初始化数据库 @override public void init(servletconfig config) throws servletexception { //加载驱动 try { this.dburl = config.getinitparameter("dburl"); this.driverclassname = config.getinitparameter("driverclassname"); this.username = config.getinitparameter("username"); this.password = config.getinitparameter("password"); class.forname(driverclassname); } catch (classnotfoundexception e) { // todo auto-generated catch block e.printstacktrace(); } } @override protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { //第二步:通过code换取网页授权access_token //从request里面获取code参数(当微信服务器访问回调地址的时候,会把code参数传递过来) string code = request.getparameter("code"); system.out.println("code:"+code); //获取code后,请求以下链接获取access_token string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + authutil.appid + "&secret=" + authutil.appsecret + "&code=" + code + "&grant_type=authorization_code"; //通过网络请求方法来请求上面这个接口 jsonobject jsonobject = authutil.dogetjson(url); system.out.println("==========================jsonobject"+jsonobject); //从返回的json数据中取出access_token和openid,拉取用户信息时用 string token = jsonobject.getstring("access_token"); string openid = jsonobject.getstring("openid"); // 第三步:刷新access_token(如果需要) // 第四步:拉取用户信息(需scope为 snsapi_userinfo) string infourl ="https://api.weixin.qq.com/sns/userinfo?access_token=" + token + "&openid=" + openid + "&lang=zh_cn"; //通过网络请求方法来请求上面这个接口 jsonobject userinfo = authutil.dogetjson(infourl); system.out.println(userinfo); //第1种情况:使用微信用户信息直接登录,无需注册和绑定 // request.setattribute("info", userinfo); //直接跳转 // request.getrequestdispatcher("/index1.jsp").forward(request, response); //第2种情况: 将微信与当前系统的账号进行绑定(需将第1种情况和@webservlet("/callback")注释掉) //第一步,根据当前openid查询数据库,看是否该账号已经进行绑定 try { string nickname = getnickname(openid); if(!"".equals(nickname)){ //已绑定 request.setattribute("nickname", nickname); request.getrequestdispatcher("/index2.jsp").forward(request, response); }else{ //未绑定 request.setattribute("openid", openid); request.getrequestdispatcher("/login.jsp").forward(request, response); } } catch (sqlexception e) { // todo auto-generated catch block e.printstacktrace(); } } //数据库的查询 public string getnickname(string openid) throws sqlexception{ string nickname = ""; //创建数据库链接 conn = drivermanager.getconnection(dburl, username, password); string sql = "select nickname from user where openid = ?"; ps = conn.preparestatement(sql); ps.setstring(1, openid); rs = ps.executequery(); while (rs.next()) { nickname = rs.getstring("nickname"); } //关闭链接 rs.close(); ps.close(); conn.close(); return nickname; } //数据库的修改(openid的綁定) public int updateuser(string account,string password,string openid) throws sqlexception{ //创建数据库链接 conn = drivermanager.getconnection(dburl, username, password); string sql = "update user set openid = ? where account = ? and password = ?"; ps = conn.preparestatement(sql); ps.setstring(1, openid); ps.setstring(2, account); ps.setstring(3, password); int temp = ps.executeupdate(); //关闭链接 rs.close(); ps.close(); conn.close(); return temp; } //post方法,用来接受登录请求 @override protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { string account = request.getparameter("account"); string password = request.getparameter("password"); string openid = request.getparameter("openid"); try { int temp = updateuser(account, password, openid); if(temp > 0){ string nickname = getnickname(openid); request.setattribute("nickname", nickname); request.getrequestdispatcher("/index2.jsp").forward(request, response); system.out.println("账号绑定成功"); }else{ system.out.println("账号绑定失败"); } } catch (sqlexception e) { // todo auto-generated catch block e.printstacktrace(); } } }
login.jsp
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>insert title here</title> </head> <body> <form action="/wxauth/wxcallback" method="post"> <input type="text" name="account" /> <input type="password" name="password" /> <input type="hidden" name="openid" value="${openid }" /> <input type="submit" value="提交并绑定" /> </form> </body> </html>
index.jsp
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>insert title here</title> </head> <body style="font-size: 40px; text-align: center;"> <a href="/wxauth/wxlogin" rel="external nofollow" >微信公众授权登录</a> </body> </html>
index1.jsp
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>insert title here</title> </head> <body> <div>登陆成功!</div> <div>用户昵称:${info.nickname}</div> <div>用户头像:<img style="text-align: top;" width="100" src="${info.headimgurl }"></div> </body> </html>
index2.jsp
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>insert title here</title> </head> <body> <div>登陆成功!</div> <div>用户昵称:${nickname}</div> </body> </html>
最后附上需要的jar包
到此,微信授权登录成功,如果有运行问题请自行调试,我这边能正常运行的
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: mysql中IFNULL,IF,CASE的区别介绍
下一篇: 如何使用ASP.NET制作简单的验证码