一 準備
1 httpclient工具類
package com.atguigu.guli.common.base.util;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @className: HttpClientUtils
* @description: http請求客戶端
* @date: 2021/1/2
* @author: cakin
*/
public class HttpClientUtils {
private String url;
private Map<String, String> param;
private int statusCode;
private String content;
private String xmlParam;
private boolean isHttps;
public boolean isHttps() {
return isHttps;
}
public void setHttps(boolean isHttps) {
this.isHttps = isHttps;
}
public String getXmlParam() {
return xmlParam;
}
public void setXmlParam(String xmlParam) {
this.xmlParam = xmlParam;
}
public HttpClientUtils(String url, Map<String, String> param) {
this.url = url;
this.param = param;
}
public HttpClientUtils(String url) {
this.url = url;
}
public void setParameter(Map<String, String> map) {
param = map;
}
public void addParameter(String key, String value) {
if (param == null)
param = new HashMap<String, String>();
param.put(key, value);
}
public void post() throws ClientProtocolException, IOException {
HttpPost http = new HttpPost(url);
setEntity(http);
execute(http);
}
public void put() throws ClientProtocolException, IOException {
HttpPut http = new HttpPut(url);
setEntity(http);
execute(http);
}
public void get() throws ClientProtocolException, IOException {
if (param != null) {
StringBuilder url = new StringBuilder(this.url);
boolean isFirst = true;
for (String key : param.keySet()) {
if (isFirst) {
url.append("?");
isFirst = false;
}else {
url.append("&");
}
url.append(key).append("=").append(param.get(key));
}
this.url = url.toString();
}
HttpGet http = new HttpGet(url);
execute(http);
}
/**
* set http post,put param
*/
private void setEntity(HttpEntityEnclosingRequestBase http) {
if (param != null) {
List<NameValuePair> nvps = new LinkedList<NameValuePair>();
for (String key : param.keySet())
nvps.add(new BasicNameValuePair(key, param.get(key))); // 參數
http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 設置參數
}
if (xmlParam != null) {
http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
}
}
private void execute(HttpUriRequest http) throws ClientProtocolException,
IOException {
CloseableHttpClient httpClient = null;
try {
if (isHttps) {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(null, new TrustStrategy() {
// 信任所有
public boolean isTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext);
httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
.build();
} else {
httpClient = HttpClients.createDefault();
}
CloseableHttpResponse response = httpClient.execute(http);
try {
if (response != null) {
if (response.getStatusLine() != null)
statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
// 響應內容
content = EntityUtils.toString(entity, Consts.UTF_8);
}
} finally {
response.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpClient.close();
}
}
public int getStatusCode() {
return statusCode;
}
public String getContent() throws ParseException, IOException {
return content;
}
}
2 pom依賴
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
二 獲取access_token
/**
* 功能描述:阿里雲對本地的回調
*
* @param code 認證code
* @param state 認證狀態
* @param session session
* @return
* @author cakin
* @date 2021/1/2
* @description:
*/
@GetMapping("callback")
public String callback(String code, String state, HttpSession session) {
System.out.println("callback被調用");
System.out.println("code:" + code);
System.out.println("state:" + state);
if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) {
log.error("非法回調請求");
throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
}
String sessionState = (String) session.getAttribute("wx_open_state");
if (!state.equals(sessionState)) {
log.error("非法回調請求");
throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
}
// 攜帶code臨時票據,和appid以及appsecret請求access_token和openid(微信唯一標識)
String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
//組裝參數:?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
Map<String, String> accessTokenParam = new HashMap<>();
accessTokenParam.put("appid", ucenterProperties.getAppId());
accessTokenParam.put("secret", ucenterProperties.getAppSecret());
accessTokenParam.put("code", code);
accessTokenParam.put("grant_type", "authorization_code");
HttpClientUtils client = new HttpClientUtils(accessTokenUrl, accessTokenParam);
String result;
try {
// 發送請求:組裝完整的url字符串、發送請求
client.get();
// 得到響應
result = client.getContent();
System.out.println("result = " + result);
} catch (Exception e) {
log.error("獲取access_token失敗");
throw new GuliException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
}
Gson gson = new Gson();
HashMap<String, Object> resultMap = gson.fromJson(result, HashMap.class);
// 失敗的響應結果
Object errcodeObj = resultMap.get("errcode");
if (errcodeObj != null) {
Double errcode = (Double) errcodeObj;
String errmsg = (String) resultMap.get("errmsg");
log.error("獲取access_token失敗:" + "code:" + errcode + ", message:" + errmsg);
throw new GuliException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
}
// 成功響應:解析出結果中的access_token和openid
String accessToken = (String) resultMap.get("access_token");
String openid = (String) resultMap.get("openid");
System.out.println("accessToken:" + accessToken);
System.out.println("openid:" + openid);
return null;
}
三 獲取用戶信息
1 根據openid查詢用戶是否已註冊
接口
/**
* 功能描述:根據openid查詢用戶是否已註冊
*
* @author cakin
* @date 2021/1/2
* @param openid openid
* @return Member 用戶信息
*/
Member getByOpenid(String openid);
實現
/**
* 功能描述:根據openid查詢用戶是否已註冊
*
* @param openid openid
* @return Member 用戶信息
* @author cakin
* @date 2021/1/2
*/
@Override
public Member getByOpenid(String openid) {
QueryWrapper<Member> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("openid", openid);
return baseMapper.selectOne(queryWrapper);
}
2 根據access_token獲取用戶信息
/**
* 功能描述:阿里雲對本地的回調
*
* @param code 認證code
* @param state 認證狀態
* @param session session
* @return
* @author cakin
* @date 2021/1/2
* @description:
*/
@GetMapping("callback")
public String callback(String code, String state, HttpSession session) {
......
// 在本地數據庫中查找當前微信用戶的信息
Member member = memberService.getByOpenid(openid);
// 沒有註冊情況
if (member == null) {
// 如果當前用戶不存在,則去微信的資源服務器獲取用戶個人信息(攜帶access_token)
String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo";
// 組裝參數:?access_token=ACCESS_TOKEN&openid=OPENID
Map<String, String> baseUserInfoParam = new HashMap<>();
baseUserInfoParam.put("access_token", accessToken);
baseUserInfoParam.put("openid", openid);
client = new HttpClientUtils(baseUserInfoUrl, baseUserInfoParam);
String resultUserInfo = "";
try {
client.get();
resultUserInfo = client.getContent();
} catch (Exception e) {
log.error(ExceptionUtils.getMessage(e));
throw new GuliException(ResultCodeEnum.FETCH_USERINFO_ERROR);
}
HashMap<String, Object> resultUserInfoMap = gson.fromJson(resultUserInfo, HashMap.class);
// 失敗的響應結果
errcodeObj = resultUserInfoMap.get("errcode");
if (errcodeObj != null) {
Double errcode = (Double) errcodeObj;
String errmsg = (String) resultMap.get("errmsg");
log.error("獲取用戶信息失敗:" + "code:" + errcode + ", message:" + errmsg);
throw new GuliException(ResultCodeEnum.FETCH_USERINFO_ERROR);
}
// 解析出結果中的用戶個人信息
String nickname = (String) resultUserInfoMap.get("nickname");
String avatar = (String) resultUserInfoMap.get("headimgurl");
Double sex = (Double) resultUserInfoMap.get("sex");
// 在本地數據庫中插入當前微信用戶的信息(使用微信賬號在本地服務器註冊新用戶)
member = new Member();
member.setOpenid(openid);
member.setNickname(nickname);
member.setAvatar(avatar);
member.setSex(sex.intValue());
memberService.save(member);
}
// 則直接使用當前用戶的信息登錄(生成jwt)
// member =>Jwt
JwtInfo jwtInfo = new JwtInfo();
jwtInfo.setId(member.getId());
jwtInfo.setNickname(member.getNickname());
jwtInfo.setAvatar(member.getAvatar());
String jwtToken = JwtUtils.getJwtToken(jwtInfo, 1800);
return "redirect:http://localhost:3000?token=" + jwtToken;
}
四 前端整合
// 頁面渲染之後執行:可以有window對象
mounted() {
const token = this.$route.query.token
if (token) {
// 將jwt寫入cookie
cookie.set('guli_jwt_token', token, { domain: 'localhost' })
window.location.href = '/'
}
},