準(zhǔn)備工作
網(wǎng)站接入
登陸微博開放平臺座享,進(jìn)入微連接绍绘,選擇網(wǎng)站接入image.png
image.png
開發(fā)者信息認(rèn)證
填寫開發(fā)者信息與身份認(rèn)證信息image.png
創(chuàng)建應(yīng)用
開發(fā)者信息認(rèn)證通過后即可創(chuàng)建應(yīng)用凌外。image.png
應(yīng)用創(chuàng)建成功后會得到app key
和app secret
image.png
image.png
image.png
流程分析
Web網(wǎng)站的授權(quán)流程如下image.png
引導(dǎo)授權(quán)用戶
引導(dǎo)需要授權(quán)的用戶到如下地址
https://api.weibo.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI
<a >
<span>微博</span>
</a>
image.png
用戶授權(quán)
來到授權(quán)地址后歉备,需要用戶授權(quán)常摧,授權(quán)成功返回Code碼
image.png
授權(quán)成功
如果用戶同意授權(quán),頁面跳轉(zhuǎn)至回調(diào)地址
并攜帶Code
碼
image.png
換取Access Token
通過授權(quán)返回的CODE
威创,請求如下地址落午,換取Access Token。
https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&code=CODE
https://api.weibo.com/oauth2/access_token?code=0c55753fe19a5bcf0a4a42afd4a64353&grant_type=authorization_code&client_secret=81abcdefghijkmllb4a45f4288ef&redirect_uri=https://ws20264753.zicp.fun/weibo/success&client_id=231234566
得到如下響應(yīng)結(jié)果
body: {"access_token":"2.00123456789480Ngwx8","remind_in":"15896999","expires_in":157679999,"uid":"12345678","isRealName":"true"}
HTTP客戶端
Code獲取后肚豺,需要使用Code獲取Access Token溃斋,以及使用token請求其他接口,此時需要使用發(fā)送請求的HTTP客戶端吸申,這里使用hutool工具類
發(fā)送一個POST請求示例:
//鏈?zhǔn)綐?gòu)建請求
String result2 = HttpRequest.post(url)
.header(Header.USER_AGENT, "Hutool http")//頭信息梗劫,多個頭信息多次調(diào)用此方法即可
.form(paramMap)//表單內(nèi)容
.timeout(20000)//超時,毫秒
.execute().body();
Console.log(result2);
使用Access Token請求相關(guān)接口
Access Token得到后截碴,就可以使用Access Token請求相關(guān)接口獲取對應(yīng)數(shù)據(jù)梳侨,這里使用2個接口舉例使用說明。
相關(guān)接口如下:
image.png
根據(jù)用戶ID獲取用戶信息
根據(jù)用戶ID獲取用戶信息接口描述信息如下image.png
只需要如下設(shè)置請求參數(shù)日丹,請求地址即可獲取用戶信息
Map<String, Object> selectUserParam = new HashMap<>();
selectUserParam.put("access_token", "token");
selectUserParam.put("uid", "uid");
HttpResponse execute = HttpRequest.get("https://api.weibo.com/2/users/show.json").form(selectUserParam).timeout(2000).execute();
響應(yīng)如下類似信息
{
"id": 51234100,
"idstr": "58812345464100",
"class": 1,
"screen_name": "XX",
"name": "XX",
"province": "51",
"city": "14",
"location": "四川 成都",
"description": "真正的強(qiáng)者走哺,不是流淚的人,而是含淚奔跑的人哲虾。",
"url": "",
"profile_image_url": "https://tva3.sinaimg.cn/crop.0.0.996.996.50/006qils8jw8f2cztnnp6vj30ro0rpgnj.jpg?KID=imgbed,tva&Expires=1663398489&ssig=JM0ZTUEYbs",
"light_ring": false,
"cover_image_phone": "http://ww1.sinaimg.cn/crop.0.0.640.640.640/549d0121tw1egm1kjly3jj20hs0hsq4f.jpg",
"profile_url": "u/58812345464100",
"domain": "",
"weihao": "",
"gender": "m",
}
獲取用戶的粉絲列表
獲取用戶的粉絲列表接口描述信息如下image.png
Map<String, Object> selectUserParam = new HashMap<>();
selectUserParam.put("access_token", weiboUser.getAccess_token());
selectUserParam.put("uid", weiboUser.getUid());
HttpResponse execute = HttpRequest.get("https://api.weibo.com/2/friendships/followers.json").form(selectUserParam).timeout(2000).execute();
響應(yīng)結(jié)果
粉絲信息: {"users":[],"has_filtered_attentions":false,"next_cursor":600,"previous_cursor":0,"total_number":1789,"use_sink_stragety":false,"has_filtered_fans":true,"use_status_strategy":false,"show_related_topic":false,"display_total_number":1789,"display_total_number_str":"1789","show_unread":false}
Spring Boot集成微博登錄
添加依賴
添加hutool開發(fā)工具包丙躏,核心用于發(fā)送Http請求择示。
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.2</version>
</dependency>
<!-- thymeleaf頁面 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
封裝Token等信息
用戶授權(quán)成功后,使用WeiboUser類封裝相關(guān)信息
/**
* 封裝登錄認(rèn)證后的令牌等信息
*/
@Data
public class WeiboUser {
/**
* 令牌
*/
private String access_token;
/**
* 令牌過期時間,該參數(shù)即將廢棄
*/
private String remind_in;
/**
* 令牌過期時間,單位是秒數(shù)
*/
private long expires_in;
/**
* 該社交用戶的唯一標(biāo)識
*/
private String uid;
/**
* 是否記住我
*/
private String isRealName;
}
創(chuàng)建Login頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<a >
<span>微博</span>
</a>
</div>
</body>
</html>
創(chuàng)建Home頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<h3>登錄成功</h3>
</div>
</body>
</html>
微博登錄邏輯
package com.example.demo.controller;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Controller
public class WeiBoController {
@RequestMapping("/weibo/login")
public String login() {
return "login";
}
@RequestMapping("/weibo/success")
public String authorize(String code, HttpSession session) throws Exception {
// 使用code換取token晒旅,換取成功則繼續(xù)栅盲,否則重定向登錄頁
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("client_id", "2312345676");
paramMap.put("client_secret", "819b8cd2dbd1f188dbedb4a45f4288ef");
paramMap.put("grant_type", "authorization_code");
paramMap.put("redirect_uri", "https://ws20264753.zicp.fun/weibo/success");
paramMap.put("code", code);
String url = this.buildUrl("https://api.weibo.com", "/oauth2/access_token", paramMap);
//發(fā)送post請求換取token
HttpResponse httpResponse = HttpRequest.post(url)
.timeout(20000)//超時,毫秒
.execute();
Map<String, String> errors = new HashMap<>();
if (httpResponse.getStatus() == 200) {
String body = httpResponse.body();
log.info("body: {}", body);
WeiboUser weiboUser = JSON.parseObject(body, WeiboUser.class);
// TODO 使用 weiboUser.getUid() 查詢數(shù)據(jù)庫 若查詢結(jié)果為null废恋,則之前未登陸過谈秫,查詢其社交信息進(jìn)行注冊
Boolean selectUser = true;
if (selectUser) {
log.info("用戶未注冊,查詢用戶信息進(jìn)行注冊");
this.register(weiboUser);
// 獲取粉絲信息
this.getFan(weiboUser);
} else {
log.info("用戶已注冊鱼鼓,更新相關(guān)信息");
// TODO 更新TOKEN拟烫、UID、登錄過期時間等信息
weiboUser.getAccess_token();
weiboUser.getUid();
weiboUser.getExpires_in();
}
// 將用戶信息返回
session.setAttribute("userInfo", weiboUser.toString());
return "home";
} else {
errors.put("msg", "獲得第三方授權(quán)失敗蚓哩,請重試");
session.setAttribute("errors", errors);
return "login";
}
}
@RequestMapping("/weibo/fail")
public void authorize() {
log.info("weibo fail...");
}
/**
* 獲取用戶信息
*/
public void register(WeiboUser weiboUser) {
Map<String, Object> selectUserParam = new HashMap<>();
selectUserParam.put("access_token", weiboUser.getAccess_token());
selectUserParam.put("uid", weiboUser.getUid());
// String selectUserUrl = this.buildUrl("https://api.weibo.com", "/2/users/show.json", selectUserParam);
HttpResponse execute = HttpRequest.get("https://api.weibo.com/2/users/show.json").form(selectUserParam).timeout(2000).execute();
if (execute.getStatus() == 200) {
String userInfo = execute.body();
log.info("userInfo: {}", userInfo);
//TODO 調(diào)用微博api接口獲取用戶信息,然后進(jìn)行注冊,記錄以下值
weiboUser.getAccess_token();
weiboUser.getUid();
weiboUser.getExpires_in();
}
}
/**
* 獲取
*/
public void getFan(WeiboUser weiboUser) {
Map<String, Object> selectUserParam = new HashMap<>();
selectUserParam.put("access_token", weiboUser.getAccess_token());
selectUserParam.put("uid", weiboUser.getUid());
// String selectUserUrl = this.buildUrl("https://api.weibo.com", "/2/users/show.json", selectUserParam);
HttpResponse execute = HttpRequest.get("https://api.weibo.com/2/friendships/followers.json").form(selectUserParam).timeout(2000).execute();
if (execute.getStatus() == 200) {
String fanList = execute.body();
log.info("粉絲信息: {}", fanList);
}
}
/**
* 構(gòu)建請求URl地址
*
* @return
*/
private static String buildUrl(String host, String path, Map<String, Object> querys) throws
UnsupportedEncodingException {
StringBuilder sbUrl = new StringBuilder();
sbUrl.append(host).append(path);
StringBuilder sbQuery = new StringBuilder();
for (Map.Entry<String, Object> query : querys.entrySet()) {
if (sbQuery.length() > 0) {
sbQuery.append("&");
}
sbQuery.append(query.getKey());
sbQuery.append("=");
sbQuery.append(URLEncoder.encode(query.getValue().toString(), "utf-8"));
}
if (sbQuery.length() > 0) {
sbUrl.append("?").append(sbQuery);
}
return sbUrl.toString();
}
}