How to Integrate QQ Login in Spring Boot: Step‑by‑Step Guide
This tutorial walks you through registering a QQ Connect application, adding the required Maven dependency, creating the login page, implementing the Spring Boot controller and AuthComment utility class, configuring Freemarker, and handling the OAuth flow to achieve seamless QQ authentication in a Java backend.
QQ Connect Account Registration
Visit https://connect.qq.com/ , create a new application, and fill in the required information. After submission you can find the APP ID and APP Key in the application management console.
Adding the QQ Login Dependency
<!-- Third‑party QQ login -->
<dependency>
<groupId>com.qq</groupId>
<artifactId>Sdk4J</artifactId>
<version>2</version>
</dependency>Login Page
<button type="submit" class="btn btn-default" onclick="qqLogin()">qq登录</button>
function qqLogin() {
window.open("/login/qqLogin", "TencentLogin");
}Login Controller Implementation
package com.gbq.boot.web.controller;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.gbq.boot.web.bean.User;
import com.gbq.boot.web.comment.qqLoginComment.AuthComment;
import com.gbq.boot.web.service.UserService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
/**
* Login Controller
*/
@RestController
@RequestMapping("/login")
public class LoginController {
@Resource
private UserService userService;
@Resource
private AuthComment authComment;
@RequestMapping("/index")
public ModelAndView index(@ModelAttribute("user") User user) {
return new ModelAndView("/shop/index", "user", user);
}
@RequestMapping("/login.html")
public ModelAndView toLogin() {
return new ModelAndView("login");
}
@RequestMapping("/qqLogin")
public void qqLogin(HttpServletResponse response) throws Exception {
String state = StrUtil.uuid();
String url = authComment.getAuthUrl(state);
System.out.println(url);
response.sendRedirect(url);
}
@GetMapping("/redirect")
public ModelAndView getData(@RequestParam(value = "code") String code, RedirectAttributes model) {
String accessToken = authComment.getAccessToken(code);
System.out.println("accessToken" + accessToken);
String openId = authComment.getOpenId(accessToken);
System.out.println("openId" + openId);
JSONObject userInfo = authComment.getUserInfo(accessToken, openId);
String myName = userInfo.getString("nickname");
User user = new User(null, "", "111111", myName, System.currentTimeMillis(), "是",
userInfo.getString("figureurl_2"), userInfo.getString("gender"),
1, 1, "", "", openId);
User usr = userService.findUsrByOpenId(openId);
if (usr != null) {
user.setId(usr.getId());
userService.updateById(user);
} else {
userService.insert(user);
}
model.addFlashAttribute("user", user);
return new ModelAndView("redirect:/login/index");
}
}AuthComment Utility Class
package com.gbq.boot.web.comment.qqLoginComment;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.apache.commons.io.IOUtils.toByteArray;
@Component
public class AuthComment {
private static final String AUTHORIZATION_URL = "https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=%s&redirect_uri=%s&scope=%s";
private static final String ACCESS_TOKEN_URL = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id=%s&client_secret=%s&code=%s&redirect_uri=%s";
private static final String OPEN_ID_URL = "https://graph.qq.com/oauth2.0/me?access_token=%s";
private static final String USER_INFO_URL = "https://graph.qq.com/user/get_user_info?access_token=%s&oauth_consumer_key=%s&openid=%s";
private static final String CALLBACK_URL = "http://127.0.0.1:8080/login/redirect";
private static final String APP_ID = "你的id"; // replace with your APP ID
private static final String APP_SECRET = "你的key"; // replace with your APP Key
public String getAuthUrl(String scope) {
return String.format(AUTHORIZATION_URL, APP_ID, CALLBACK_URL, scope);
}
public String getAccessToken(String code) {
String url = String.format(ACCESS_TOKEN_URL, APP_ID, APP_SECRET, code, CALLBACK_URL);
String result = getUrl(url);
return getMatcher(result, "access_token=(\\w*)&");
}
public String getOpenId(String accessToken) {
String url = String.format(OPEN_ID_URL, accessToken);
String result = getUrl(url);
return getMatcher(result, "openid\":\"(\\w*)\"");
}
public JSONObject getUserInfo(String accessToken, String openId) {
String url = String.format(USER_INFO_URL, accessToken, APP_ID, openId);
String result = getUrl(url);
return JSON.parseObject(result);
}
private String getMatcher(String result, String patternStr) {
Pattern p = Pattern.compile(patternStr);
Matcher m = p.matcher(result);
m.find();
return m.group(1);
}
private String getUrl(String urlStr) {
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setRequestMethod("GET");
InputStream in = conn.getInputStream();
byte[] data = toByteArray(in);
return new String(data, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}Freemarker Configuration (Spring Boot)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
freemarker:
template-loader-path: classpath:/templates/
suffix: .ftl
cache: false
charset: UTF-8
check-template-location: true
content-type: text/html
enabled: true
mvc:
view:
prefix: /templates/
suffix: .html
static-path-pattern: /static/**Success Page Example
<span>欢迎你,${user.name}</span>After completing the above steps, the application can redirect users to QQ for authentication, retrieve the access token, openId, and user profile (nickname, avatar URLs, etc.), and log the user in using the data stored in the backend.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
