解釋微信作為第三方授權登入
阿新 • • 發佈:2019-01-09
微信開放平臺的官網https://open.weixin.qq.com/,
這裡是文件,
這個圖看著來,
1. 使用者點選微信登入,這時請求我們自己的應用(一個藉口,該介面給頁面返回一個微信端的登入地址)。
其中的appid是在開放平臺註冊應用後獲取的secret也是,redirect_uri 是告訴微信,用後授權後,微信需要對我們進行回撥的介面(把臨時授權code,返回這個介面)這個地址也要與註冊的一致。state:我看視屏的時候,這個傳你登入的頁面,也就是登入成功後想到到的頁面(官方解釋:用於保持請求和回撥的狀態,授權請求後原樣帶回給第三方。該引數可用於防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該引數,可設定為簡單的隨機數加session進行校驗)
2. 根據第一步獲取的登入地址,頁面請求載入微信的登入頁面,然後進行確認。
3. 確認後微信會對我們自己的應用進行一個回撥,並且給我們一個臨時的授權code。
4.根據code+appid+appsecret 請求微信能獲取使用者資訊的access_token。
5.微信返回access_token,我們進行解析,處理儲存等。
感覺寫的有點水,權當記錄了,輕點噴……
package com.lpw.dbvideo.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; /** * 微信配置類 */ @Configuration @PropertySource(value = "classpath:application.properties") public class WeChatConfig { /** * 微信公眾號AppId */ @Value("${wx.oa.appid}") private String wxOAAppId; /** * 微信公眾號AppSecret */ @Value("${wx.oa.appsecret}") private String wxOAAppSecret; /** * 微信開放平臺 openappid */ @Value("${wx.open.appid}") private String wxOpenAppId; /** * 微信開放平臺 openappsecret */ @Value("${wx.open.appsecret}") private String wxOpenSecret; /** * 微信開放平臺重定向地址 */ @Value("${wx.open.redirecturl}") private String wxOpenRedirectUrl; /** * 微信開放平臺二維碼地址 */ // private static final String OPEN_QRCODE_URL = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect"; private static final String OPEN_QRCODE_URL = "127.0.0.1:8081/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=SCOPE&state=%s#wechat_redirect"; /** * 開放平臺獲取access_token 地址 */ private static final String OPEN_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"; /** * 獲取微信使用者資訊的介面 */ private static final String OPEN_USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s"; public String getWxOAAppId() { return wxOAAppId; } public void setWxOAAppId(String wxOAAppId) { this.wxOAAppId = wxOAAppId; } public String getWxOAAppSecret() { return wxOAAppSecret; } public void setWxOAAppSecret(String wxOAAppSecret) { this.wxOAAppSecret = wxOAAppSecret; } public String getWxOpenAppId() { return wxOpenAppId; } public void setWxOpenAppId(String wxOpenAppId) { this.wxOpenAppId = wxOpenAppId; } public String getWxOpenSecret() { return wxOpenSecret; } public void setWxOpenSecret(String wxOpenSecret) { this.wxOpenSecret = wxOpenSecret; } public String getWxOpenRedirectUrl() { return wxOpenRedirectUrl; } public void setWxOpenRedirectUrl(String wxOpenRedirectUrl) { this.wxOpenRedirectUrl = wxOpenRedirectUrl; } public static String getOpenQrcodeUrl() { return OPEN_QRCODE_URL; } public static String getOpenAccessTokenUrl() { return OPEN_ACCESS_TOKEN_URL; } public static String getOpenUserInfoUrl() { return OPEN_USER_INFO_URL; } }
package com.lpw.dbvideo.login.controller; import com.lpw.dbvideo.config.WeChatConfig; import com.lpw.dbvideo.user.service.UserService; import com.lpw.dbvideo.utils.JsonData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; /** * 第一步 使用者前端請求進入(本專案中的)介面,介面請求微信平臺,微信平臺給(本專案中的)介面返回一個授權地址,(本專案中的)介面再給前端返回,前端展示; * 第二步 使用者前端進行確認(即掃碼確認),接著微信平臺會重定向到(本專案中的)介面,並且帶上一個授權臨時票據code; * 第三步 根據code加上appid和appsecret 請求微信獲取token,微信返回token結束。 */ @Controller @RequestMapping("/api/wechat") public class WeChatController { @Autowired private WeChatConfig weChatConfig; @Autowired private UserService userService; /** * 微信掃一掃登入,獲取微信二維碼的地址 * @param state 用於保持請求和回撥的狀態,授權請求後原樣帶回給第三方。該引數可用於防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該引數,可設定為簡單的隨機數加session進行校驗 * @return * @throws UnsupportedEncodingException */ @RequestMapping("login") @ResponseBody @CrossOrigin public JsonData loginUrl(@RequestParam(value = "state")String state) throws UnsupportedEncodingException { String redirecrUrl = weChatConfig.getWxOpenRedirectUrl(); // 獲取開放平臺重定向地址 String callBackUrl = URLEncoder.encode(redirecrUrl,"UTF-8"); // 進行編碼 String qrcodeUrl = String.format(WeChatConfig.getOpenQrcodeUrl(),weChatConfig.getWxOpenAppId(),callBackUrl,state); return JsonData.success(qrcodeUrl); } /** * 微信客戶端的回撥介面 * @param code 使用者確認後,微信端重定向會這個介面,帶上授權臨時票據(code) * @param state 上面我們給微信端傳的state,微信端會繼續返回給我們 * @param response HttpServletResponse */ @GetMapping("/user/callback") public void wechatUserCallBack(String code, String state, HttpServletResponse response){ userService.saveWeChatUser(code); } }
package com.lpw.dbvideo.utils;
import com.google.gson.Gson;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.util.HashMap;
import java.util.Map;
/**
* 封裝http get,post
*/
public class HttpUtils {
public static final Gson gson = new Gson();
/**
* get方法
* @param url
* @return
*/
public static Map<String, Object> doGet(String url){
Map<String, Object> map = new HashMap<String, Object>();
CloseableHttpClient httpClient = HttpClients.createDefault();
RequestConfig requestConfig =RequestConfig.custom().setConnectTimeout(5000) // 連線超時
.setConnectionRequestTimeout(5000) // 請求超時
.setSocketTimeout(5000) // 連線socket超時
.setRedirectsEnabled(true) // 允許重定向
.build();
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(requestConfig);
try{
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
String jsonResult = EntityUtils.toString(httpResponse.getEntity());
map = gson.fromJson(jsonResult, map.getClass());
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
httpClient.close();
}catch (Exception e){
e.printStackTrace(); }
}
return map;
}
/**
* 封裝 post
* @param url 請求路徑
* @param data 請求資料
* @param timeout 過期時間
* @return
*/
public static String doPost(String url, String data,int timeout ){
CloseableHttpClient httpClient = HttpClients.createDefault();
// 設定超時
RequestConfig requestConfig =RequestConfig.custom().setConnectTimeout(timeout) // 連線超時
.setConnectionRequestTimeout(timeout) // 請求超時
.setSocketTimeout(timeout) // 連線socket超時
.setRedirectsEnabled(true) // 允許重定向
.build();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
httpPost.addHeader("Content-type", "text/html;charset=UTF-8");
if(data != null && data instanceof String){
StringEntity stringEntity = new StringEntity(data, "UTF-8");
httpPost.setEntity(stringEntity);
}
try{
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
if(httpResponse.getStatusLine().getStatusCode() == 200){
String jsonResult = EntityUtils.toString(httpEntity);
return jsonResult;
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
httpClient.close();
}catch (Exception e){
e.printStackTrace();
}
}
return null;
}
}
<!-- httpclient 相關-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
由於測試的時候沒有開放平臺的認證賬號,所以只好自己寫一個服務模擬測試(有出入諒解,畢竟不知道微信怎麼做的)。附上碼雲地址。