Java實現微信網頁受權

開發前的準備: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包

 

 到此,微信受權登陸成功,若是有運行問題請自行調試,我這邊能正常運行的

相關文章
相關標籤/搜索