--------
Forwarding Statement: This article is reprinted to the CSDN blogger "Drunk Three Lives". It is reprinted to the CSDN blogger.
Links to the original text: https://blog.csdn.net/qq_37618797/article/details/90344835
I. Preparations
1. Cloud Server
2. Domain name for filing
3. Local debugging needs to modify hosts files to map domain names to 127.0.0.1
First, apply for QQ interconnection and become a developer
QQ interconnection: https://connect.qq.com/index.html
After login, click on the avatar, enter the authentication page, fill in the information, and wait for review.
After approval, click Create Application
After the audit is approved, you can use APP ID and APP Key
2. Writing java code
github:https://github.com/sansheng741/QQLogin
Project structure
yml configuration
server: port: 80 qq: oauth: http: //Website Address Filled in QQ Interconnection
Importing pom dependencies
<!--httpclient--> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.6</version> </dependency> <!--Ali JSON--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency>
QQController
package com.ck.blog.controller; import com.alibaba.fastjson.JSONObject; import com.ck.blog.exception.StateErrorException; import com.ck.blog.utils.QQHttpClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.net.URLEncoder; import java.util.UUID; /** * @author ck * @create 2019-05-18 20:32 */ @Controller public class QQController { @Value("${qq.oauth.http}") private String http; /** * Initiate request * @param session * @return */ @GetMapping("/qq/oauth") public String qq(HttpSession session){ //Callback Address in QQ Interconnection String backUrl = http + "/qq/callback"; //Preventing CSRF attacks for third-party applications String uuid = UUID.randomUUID().toString().replaceAll("-",""); session.setAttribute("state",uuid); //Step1: Get Authorization Code String url = "https://graph.qq.com/oauth2.0/authorize?response_type=code"+ "&client_id=" + QQHttpClient.APPID + "&redirect_uri=" + URLEncoder.encode(backUrl) + "&state=" + uuid; return "redirect:" + url; } /** * QQ Callback * @param request * @return */ @GetMapping("/qq/callback") public String qqcallback(HttpServletRequest request) throws Exception { HttpSession session = request.getSession(); //Information returned by qq: http://graph.qqq.com/demo/index.jsp?Code=9A5F**************************************************** 06AF&state=test String code = request.getParameter("code"); String state = request.getParameter("state"); String uuid = (String) session.getAttribute("state"); if(uuid != null){ if(!uuid.equals(state)){ throw new StateErrorException("QQ,state error"); } } //Step2: Get Access Token through Authorization Code String backUrl = http + "/qq/callback"; String url = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code"+ "&client_id=" + QQHttpClient.APPID + "&client_secret=" + QQHttpClient.APPKEY + "&code=" + code + "&redirect_uri=" + backUrl; String access_token = QQHttpClient.getAccessToken(url); //Step3: Get the openid value after the callback url = "https://graph.qq.com/oauth2.0/me?access_token=" + access_token; String openid = QQHttpClient.getOpenID(url); //Step4: Getting QQ user information url = "https://graph.qq.com/user/get_user_info?access_token=" + access_token + "&oauth_consumer_key="+ QQHttpClient.APPID + "&openid=" + openid; JSONObject jsonObject = QQHttpClient.getUserInfo(url); //You can also put it in Redis and mysql session.setAttribute("openid",openid); //openid, used to uniquely identify qq users session.setAttribute("nickname",(String)jsonObject.get("nickname")); //QQ name session.setAttribute("figureurl_qq_2",(String)jsonObject.get("figureurl_qq_2")); //QQ header URL with 100*100 pixels in size return "redirect:/home"; } }
QQHttpClient
package com.ck.blog.utils; import com.alibaba.fastjson.JSONObject; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; /** * @author ck * @create 2019-05-18 20:32 * QQ Tool class (mainly for parsing information returned by QQ) */ public class QQHttpClient { //appid and appkey provided in QQ interconnection public static final String APPID = "xxxxxxxx"; public static final String APPKEY = "xxxxxxxxxx"; private static JSONObject parseJSONP(String jsonp){ int startIndex = jsonp.indexOf("("); int endIndex = jsonp.lastIndexOf(")"); String json = jsonp.substring(startIndex + 1,endIndex); return JSONObject.parseObject(json); } //qq return information: access_token = FE04******************************************************** CCE2 & expires_in = 7776000 & refresh_token = 88E4****************************** BE14 public static String getAccessToken(String url) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); String token = null; HttpGet httpGet = new HttpGet(url); HttpResponse response = client.execute(httpGet); HttpEntity entity = response.getEntity(); if(entity != null){ String result = EntityUtils.toString(entity,"UTF-8"); if(result.indexOf("access_token") >= 0){ String[] array = result.split("&"); for (String str : array){ if(str.indexOf("access_token") >= 0){ token = str.substring(str.indexOf("=") + 1); break; } } } } httpGet.releaseConnection(); return token; } //qq returns information: callback ({"client_id": "YOUR_APPID", "openid": "YOUR_OPENID"}); parseJSONP, the parsing method defined above, needs to be used. public static String getOpenID(String url) throws IOException { JSONObject jsonObject = null; CloseableHttpClient client = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(url); HttpResponse response = client.execute(httpGet); HttpEntity entity = response.getEntity(); if(entity != null){ String result = EntityUtils.toString(entity,"UTF-8"); jsonObject = parseJSONP(result); } httpGet.releaseConnection(); if(jsonObject != null){ return jsonObject.getString("openid"); }else { return null; } } //qq returns information: {"ret":0,""msg":", "nickname", "YOUR_NICK_NAME",...} in JSON format, parsed directly using JSONObject objects public static JSONObject getUserInfo(String url) throws IOException { JSONObject jsonObject = null; CloseableHttpClient client = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(url); HttpResponse response = client.execute(httpGet); HttpEntity entity = response.getEntity(); if(entity != null){ String result = EntityUtils.toString(entity,"UTF-8"); jsonObject = JSONObject.parseObject(result); } httpGet.releaseConnection(); return jsonObject; } }
IndexController
package com.ck.blog.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import javax.servlet.http.HttpSession; /** * @author ck * @create 2019-05-18 20:31 */ @Controller public class IndexController { @GetMapping("/index") public String index(){ return "index"; } @GetMapping("/home") public String home(HttpSession session, Model model){ String openid = (String) session.getAttribute("openid"); String nickname = (String) session.getAttribute("nickname"); String figureurl_qq_2 = (String) session.getAttribute("figureurl_qq_2"); model.addAttribute("openid",openid); model.addAttribute("nickname",nickname); model.addAttribute("figureurl_qq_2",figureurl_qq_2); return "home"; } }
index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Login page</title> </head> <body> <a href="/qq/oauth">QQ Authorized login</a> </body> </html>
home.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>QQ Authorized success</title> </head> <body> <div> openid:[[${openid}]] </div> <div> nickName:[[${nickname}]] </div> <div> <img th:src="${figureurl_qq_2}"> </div> </body> </html>
Design sketch