開發(fā)前的準(zhǔn)備:
1、需要有一個(gè)公眾號(我這里用的測試號),拿到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來虛擬一個(gè)域名映射到本地開發(fā)環(huán)境,網(wǎng)址https://www.ngrok.cc/,大家自己去下載學(xué)習(xí)怎么使用
同時(shí)還需要掃一下這個(gè)二維碼
授權(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)代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
<?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工具類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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)證請求接口里面,比如需要用戶在訪問頁面 時(shí)進(jìn)行授權(quán)認(rèn)證
其中的scope參數(shù)有兩個(gè)值:
snsapi_base:只能獲取到用戶openid。好處是靜默認(rèn)證,無需用戶手動點(diǎn)擊認(rèn)證按鈕,感覺上像是直接進(jìn)入網(wǎng)站一樣。
snsapi_userinfo:可以獲取到openid、昵稱、頭像、所在地等信息。需要用戶手動點(diǎn)擊認(rèn)證按鈕。
相關(guān)代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
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,通過這個(gè)code來請求access_token,通過access_token和openid獲取用戶基本信息:
相關(guān)代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
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)地址的時(shí)候,會把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ò)請求方法來請求上面這個(gè)接口 jsonobject jsonobject = authutil.dogetjson(url); system.out.println( "==========================jsonobject" +jsonobject); //從返回的json數(shù)據(jù)中取出access_token和openid,拉取用戶信息時(shí)用 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ò)請求方法來請求上面這個(gè)接口 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<%@ 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
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<%@ 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<%@ 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<%@ 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í)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://www.cnblogs.com/sutao/p/8727019.html