Java實(shí)現(xiàn)微信網(wǎng)頁授權(quán)的示例代碼
開發(fā)前的準(zhǔn)備:
1、需要有一個公眾號(我這里用的測試號),拿到AppID和AppSecret;
2、進(jìn)入公眾號開發(fā)者中心頁配置授權(quán)回調(diào)域名。具體位置:接口權(quán)限-網(wǎng)頁服務(wù)-網(wǎng)頁賬號-網(wǎng)頁授權(quán)獲取用戶基本信息-修改
注意,這里僅需填寫全域名(如www.qq.com、www.baidu.com),勿加 http:// 等協(xié)議頭及具體的地址字段;
我們可以通過使用Ngrok來虛擬一個域名映射到本地開發(fā)環(huán)境,網(wǎng)址https://www.ngrok.cc/,大家自己去下載學(xué)習(xí)怎么使用

同時還需要掃一下這個二維碼

授權(quán)步驟:
1、引導(dǎo)用戶進(jìn)入授權(quán)頁面同意授權(quán),獲取code
2、通過code換取網(wǎng)頁授權(quán)access_token(與基礎(chǔ)支持中的access_token不同)
3、通過網(wǎng)頁授權(quán)access_token和openid獲取用戶基本信息

先看一下我的項(xiàng)目結(jié)構(gòu):

web.xml相關(guān)代碼:
<?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方式進(jìn)行提交
HttpGet httpGet = new HttpGet(url);
//通過HTTPclient的execute方法進(jìn)行發(fā)送請求
HttpResponse response = client.execute(httpGet);
//從response里面拿自己想要的結(jié)果
HttpEntity entity = response.getEntity();
if(entity != null){
String result = EntityUtils.toString(entity,"UTF-8");
jsonObject = jsonObject.fromObject(result);
}
//把鏈接釋放掉
httpGet.releaseConnection();
return jsonObject;
}
}
Java實(shí)現(xiàn):
1、引導(dǎo)用戶進(jìn)入授權(quán)頁面同意授權(quán),獲取code
這一步其實(shí)就是將需要授權(quán)的頁面url拼接到微信的認(rèn)證請求接口里面,比如需要用戶在訪問頁面 時進(jìn)行授權(quán)認(rèn)證
其中的scope參數(shù)有兩個值:
snsapi_base:只能獲取到用戶openid。好處是靜默認(rèn)證,無需用戶手動點(diǎn)擊認(rèn)證按鈕,感覺上像是直接進(jìn)入網(wǎng)站一樣。
snsapi_userinfo:可以獲取到openid、昵稱、頭像、所在地等信息。需要用戶手動點(diǎn)擊認(rèn)證按鈕。
相關(guān)代碼
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 {
//第一步:引導(dǎo)用戶進(jìn)入授權(quán)頁面同意授權(quán),獲取code
//回調(diào)地址
// String backUrl = "http://suliu.free.ngrok.cc/WxAuth/callBack"; //第1種情況使用
String backUrl = "http://suliu.free.ngrok.cc/WxAuth/wxCallBack";//第2種情況使用,這里是web.xml中的路徑
//授權(quán)頁面地址
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";
//重定向到授權(quán)頁面
response.sendRedirect(url);
}
}
2、通過第一步獲取的code換取網(wǎng)頁授權(quán)access_token(與基礎(chǔ)支持中的access_token不同)
這一步需要在控制器中獲取微信回傳給我們的code,通過這個code來請求access_token,通過access_token和openid獲取用戶基本信息:
相關(guān)代碼:
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;
/**
* 回調(diào)地址
* @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;
//初始化數(shù)據(jù)庫
@Override
public void init(ServletConfig config) throws ServletException {
//加載驅(qū)動
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換取網(wǎng)頁授權(quán)access_token
//從request里面獲取code參數(shù)(當(dāng)微信服務(wù)器訪問回調(diào)地址的時候,會把code參數(shù)傳遞過來)
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";
//通過網(wǎng)絡(luò)請求方法來請求上面這個接口
JSONObject jsonObject = AuthUtil.doGetJson(url);
System.out.println("==========================jsonObject"+jsonObject);
//從返回的JSON數(shù)據(jù)中取出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";
//通過網(wǎng)絡(luò)請求方法來請求上面這個接口
JSONObject userInfo = AuthUtil.doGetJson(infoUrl);
System.out.println(userInfo);
//第1種情況:使用微信用戶信息直接登錄,無需注冊和綁定
// request.setAttribute("info", userInfo);
//直接跳轉(zhuǎn)
// request.getRequestDispatcher("/index1.jsp").forward(request, response);
//第2種情況: 將微信與當(dāng)前系統(tǒng)的賬號進(jìn)行綁定(需將第1種情況和@WebServlet("/callBack")注釋掉)
//第一步,根據(jù)當(dāng)前openid查詢數(shù)據(jù)庫,看是否該賬號已經(jīng)進(jìn)行綁定
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();
}
}
//數(shù)據(jù)庫的查詢
public String getNickName(String openid) throws SQLException{
String nickName = "";
//創(chuàng)建數(shù)據(jù)庫鏈接
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");
}
//關(guān)閉鏈接
rs.close();
ps.close();
conn.close();
return nickName;
}
//數(shù)據(jù)庫的修改(openid的綁定)
public int updateUser(String account,String password,String openid) throws SQLException{
//創(chuàng)建數(shù)據(jù)庫鏈接
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();
//關(guān)閉鏈接
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" >微信公眾授權(quán)登錄</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包

到此,微信授權(quán)登錄成功,如果有運(yùn)行問題請自行調(diào)試,我這邊能正常運(yùn)行的
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- JavaWeb項(xiàng)目打開網(wǎng)頁出現(xiàn)Session Error的異常解決方案
- java通過Jsoup爬取網(wǎng)頁過程詳解
- 詳解java實(shí)現(xiàn)簡單掃碼登錄功能(模仿微信網(wǎng)頁版掃碼)
- java調(diào)用微信接口實(shí)現(xiàn)網(wǎng)頁分享小功能
- Java實(shí)現(xiàn)的簡單網(wǎng)頁截屏功能示例
- java利用url實(shí)現(xiàn)網(wǎng)頁內(nèi)容的抓取
- 詳解JAVA抓取網(wǎng)頁的圖片,JAVA利用正則表達(dá)式抓取網(wǎng)站圖片
- Java導(dǎo)出網(wǎng)頁表格Excel過程詳解
相關(guān)文章
MyBatis 中 ${}和 #{}的正確使用方法(千萬不要亂用)
這篇文章主要介紹了MyBatis 中 ${}和 #{}的正確使用方法,本文給大家提到了MyBatis 中 ${}和 #{}的區(qū)別,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
SpringBoot?LocalDateTime格式轉(zhuǎn)換方案詳解(前端入?yún)?
這篇文章主要介紹了SpringBoot?LocalDateTime格式轉(zhuǎn)換(前端入?yún)?,本文用示例介紹SpringBoot全局格式配置,將前端傳過來的時間自動轉(zhuǎn)化為LocalDateTime,需要的朋友可以參考下2023-04-04
mybatis-plus實(shí)現(xiàn)邏輯刪除的示例代碼
本文主要介紹了mybatis-plus實(shí)現(xiàn)邏輯刪除的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
SpringBoot實(shí)現(xiàn)ORM操作MySQL的幾種方法
本文主要介紹了SpringBoot實(shí)現(xiàn)ORM操作MySQL的幾種方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02

