Java实现微信网页授权-程序员宅基地

 

微信测试平台

https://open.weixin.qq.com/connect/qrconnect?appid=wx39c379788eb1286a&scope=snsapi_login&redirect_uri=http%3A%2F%2Fmp.weixin.qq.com%2Fdebug%2Fcgi-bin%2Fsandbox%3Ft%3Dsandbox%2Flogin

开发前的准备:

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">微信公众授权登录</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包

 

jar包下载链接:

链接:https://pan.baidu.com/s/1tLJ8Z-ZFrDOv9-YduUj9Nw 密码:rmr6

 

 到此,微信授权登录成功,如果有运行问题请自行调试,我这边能正常运行的

转载于:https://www.cnblogs.com/chenlove/p/9342588.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/aici0819/article/details/101961741

智能推荐

PHP - 点击按钮请求后台下载文件_php后台下载-程序员宅基地

文章浏览阅读569次。点击按钮请求php下载文件_php后台下载

基于Pix4D使用无人机光学影像制作正射影像(DOM)和数字表面模型(DSM) 操作步骤_pix4dmapper无人机影像处理教程-程序员宅基地

文章浏览阅读5.7k次,点赞13次,收藏69次。此教程目的是让读者学会使用PIX4D拼接航片,教程较为通俗,面向初学者和专业人士。_pix4dmapper无人机影像处理教程

(7)LR如何利用siteScope监控MySQL性能_lr在性能测试怎么同时监控数据库-程序员宅基地

文章浏览阅读1.2k次。本次实验,是在自己的电脑上使用APMServ5.2.6部署Discuz2.X论坛下,对该论坛的数据库MySQL5.1进行性能测试的,下面讲述LoadRunner在设计场景时,如何利用siteScope工具监控MySQL数据库性能:一、在网上下载siteScope 我在网上搜了很久,发现siteScope软件的下载资源很少,毕竟它是收费的,想找个破解版,不过还是有的,哈哈。_lr在性能测试怎么同时监控数据库

借助知识图谱和Llama-Index实现基于大模型的RAG_llamaindex 知识图谱-程序员宅基地

文章浏览阅读1.2k次,点赞18次,收藏28次。对于语言模型(LLM)幻觉,知识图谱被证明优于向量数据库。知识图谱提供更准确、多样化、有趣、逻辑和一致的信息,减少了LLM中出现幻觉的可能性。这种优越性源于它们能够提供关于实体之间关系的精确细节,而不仅仅是表示相似性,支持更复杂的查询和逻辑推理。向量数据库以其数字数组在相似性搜索和最佳匹配场景中表现出色。最终,两者之间的选择取决于项目的需求,包括数据的性质、关系探索的需要以及预期的查询类型。_llamaindex 知识图谱

Onlyoffice本地部署超详细教程(附协作空间2.0新资讯)-程序员宅基地

文章浏览阅读4.3w次,点赞60次,收藏97次。相信大家已经有所了解ONLYOFFICE这个神中神办公软件真正的办公神器-ONLYOFFICE你了解多少?,最近公司产品突然提出一个需求要实现文档实时在线浏览编辑等一系列功能,需求评审我直接举手,这个活我来!之前对ONLYOFFICE有一定的了解,但是对于二次开发与整合方面一直没深入探索,正好借着本次机会,上班学习走起!本篇给大家讲一下ONLYOFFICE本地部署的相关步骤与注意事项。_onlyoffice

第十一届泰迪杯B题:产品订单的数据分析与需求预测_第十一届挑战赛b1-产品订单分析与需求预测 赛题数据-程序员宅基地

文章浏览阅读1.1w次,点赞38次,收藏232次。2. 基于上述分析,建立数学模型,对附件预测数据(predict_sku1.csv)中给出的产品,预测未来3月(即2019年1月、2月、3月)的月需求量,将预测结果按照表3的格式保存为文件result1.xlsx,与论文一起提交。附件中的预测数据(predict_sku1.csv)提供了需要预测产品的销售区域编码、产品编码、产品品类和产品细品类(格式见表2)。(2) 产品所在区域对需求量的影响,以及不同区域的产品需求量有何特性;(3) 不同销售方式(线上和线下)的产品需求量的特性;_第十一届挑战赛b1-产品订单分析与需求预测 赛题数据

随便推点

Docker基本管理_docker管理-程序员宅基地

文章浏览阅读982次。是一个开源的应用容器引擎,基于go语言开发并遵循了apache2.0协议开源是在Linux容器里运行应用的开源工具是一种轻量级的"虚拟机'Docker的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的、可移植的、自给自足的容器。Docker与虚拟机的区别技术支持核心概念镜像:创建容器的基础,类似于虚拟机快照,面向Docker容器引擎的只读模板容器:用镜像创建的运行实列仓库:用来保存镜像的地方3.2、镜像管理命令3.2.1、搜索镜像3.2.2、下载镜像3.2.3、_docker管理

解决C#中dll类库无法生成资源字典问题-程序员宅基地

文章浏览阅读732次。第一步:引入三个程序集:1.PresentationCore2.PresentationFramework3.WindowsBase第二步:打开此类库的工程文件 (*.csproj)//在项目的路径下中打开这个文件,不要在VS中打开在图时位置添加代码:&lt;ProjectTypeGuids&gt;{60dc8134-eba5-43b8-bcc9-bb4bc16c2...

微信小程序UI自动化测试 一、minium搭建开始_微信小程序ui自动化实践-程序员宅基地

文章浏览阅读2.1k次。1 参考文档:https://blog.csdn.net/m0_38043408/article/details/106379734?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160273112819726892421451%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=16027311281972689242_微信小程序ui自动化实践

Sora:大型视觉模型的背景、技术、局限性和机遇综述 【官方论文】,引用文章-程序员宅基地

文章浏览阅读948次,点赞27次,收藏10次。Sora:大型视觉模型的背景、技术、局限性和机遇综述 【官方论文】Web3天空之城2024-02-28 19:05:20发布于北京科技领域创作者+关注文:城主写在前面:今天微软研究院发布了Sora的深度论文综述。这里和关心Sora的同学们分享本城翻译制作的中文版(全文3.4万字)英文原版传送门:https://arxiv.org/pdf/2402.17177v1.pdf---Sora:大型视觉模型的背景、技术、局限性和机遇综述 Yixin Liu1* Kai Zhang1* Yuan

Azure Service Principal Name 验证访问-程序员宅基地

文章浏览阅读164次。【代码】Azure Service Principal Name 验证访问。_azure service principal

Python数据可视化笔记03--柱状图、饼状图实战_jupyter柱状图添加图例-程序员宅基地

文章浏览阅读6.2k次,点赞12次,收藏49次。Python数据可视化笔记01--Matplotlib基础Python数据可视化笔记02--折线图、散点图实战本文索引:柱状图 饼状图环境:Windows10 + jupyter notebook一、柱状图【柱状图】使用Matplotlib提供的bar()函数来绘制柱状图。 与前面介绍的plot()函数类似,程序每次调用bar()函数时都会生成一组柱状图,..._jupyter柱状图添加图例

推荐文章

热门文章

相关标签