開發前的準備:html
一、須要有一個公衆號(我這裏用的測試號),拿到AppID和AppSecret;java
二、進入公衆號開發者中心頁配置受權回調域名。具體位置:接口權限-網頁服務-網頁帳號-網頁受權獲取用戶基本信息-修改mysql
注意,這裏僅需填寫全域名(如www.qq.com、www.baidu.com),勿加 http:// 等協議頭及具體的地址字段;web
咱們能夠經過使用Ngrok來虛擬一個域名映射到本地開發環境,網址https://www.ngrok.cc/,你們本身去下載學習怎麼使用sql
同時還須要掃一下這個二維碼數據庫
受權步驟:apache
一、引導用戶進入受權頁面贊成受權,獲取code json
二、經過code換取網頁受權access_token(與基礎支持中的access_token不一樣) api
三、經過網頁受權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實現:
一、引導用戶進入受權頁面贊成受權,獲取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); } }
二、經過第一步獲取的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包
到此,微信受權登陸成功,若是有運行問題請自行調試,我這邊能正常運行的