How to Integrate QQ Login with Spring MVC: Step‑by‑Step Guide and Common Pitfalls

This guide walks through integrating QQ login into a Spring MVC Java application, covering environment setup, domain and callback configuration, SDK deployment, common pitfalls like non‑80‑port issues, configuration file settings, Maven dependency handling, SSL fixes, and provides a complete controller example.

Java Backend Technology
Java Backend Technology
Java Backend Technology
How to Integrate QQ Login with Spring MVC: Step‑by‑Step Guide and Common Pitfalls

Background

First time using QQ login, encountered many problems, collected solutions and recorded the steps for future reference.

Application Deployment and Common Issues

Visit the QQ Connect address to register and verify the application.

1. Account Login Use a dedicated company account for testing to avoid leaking personal QQ information. Local testing is possible; the official demo provides a method for local verification.

If deploying on a local Tomcat or other server, configure the host file with 127.0.0.1 pointing to your callback domain. Place the sdk4j_demo/web directory directly under Tomcat's webapp folder and configure conf/server.xml accordingly. Remove the Root folder temporarily. Other servers should follow their own deployment methods. Ensure the server port is set to 80 .

2. Register Developer Account Skip this step if already registered.

3. Create Application Download the SDK from the official site and follow the example project.

Key issues often involve choosing the correct website address and callback URL. The domain must resolve to port 80; other ports cause verification failures.

Example domain configuration:

Primary domain: www.abc.com (port 80)

Secondary domains can be bound via hidden URLs to different ports, e.g., www.abc.com:8012 for dubboadmin.

When using QQ login, avoid non‑80 ports; the verification process checks the meta information in the page head, which fails on other ports.

Final callback URL example: http://security.abc.com/login.do (this exact URL is used by QQ for verification).

Project Configuration File

Configure qqconnectconfig.properties with your app_ID, app_KEY, and redirect_URI (must match the callback URL). Include the required scopes.

Remember to add the QQ login JAR to the classpath.

If using Spring, place the configuration file in the resources directory; otherwise, placing it in src may cause bean loading failures.

Common Errors

SSL handshake failures can occur with OpenJDK; switch to Sun JDK to resolve javax.net.ssl.SSLKeyException.

Maven Dependency

<dependency>
  <groupId>javabuilder</groupId>
  <artifactId>javabuilder</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/Sdk4J.jar</systemPath>
</dependency>

Ensure the JAR is added to the project’s classpath.

Controller Example

@Controller
@RequestMapping
public class LoginController {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);
    @Inject
    private Oauth qqOauth;

    /**
     * QQ login entry point
     */
    @RequestMapping(value = "/qqlogin")
    public void QQLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        try {
            response.sendRedirect(qqOauth.getAuthorizeURL(request));
        } catch (QQConnectException e) {
            e.printStackTrace();
        }
    }

    /**
     * Callback after QQ login
     */
    @RequestMapping(value = "/afterQQLogin")
    protected void afterQQLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html; charset=utf-8");
        PrintWriter out = response.getWriter();
        try {
            AccessToken accessTokenObj = (new Oauth()).getAccessTokenByRequest(request);
            String accessToken = null, openID = null;
            long tokenExpireIn = 0L;
            if (accessTokenObj.getAccessToken().equals("")) {
                out.println("没有获取到响应参数");
            } else {
                accessToken = accessTokenObj.getAccessToken();
                tokenExpireIn = accessTokenObj.getExpireIn();
                request.getSession().setAttribute("demo_access_token", accessToken);
                request.getSession().setAttribute("demo_token_expirein", String.valueOf(tokenExpireIn));
                OpenID openIDObj = new OpenID(accessToken);
                openID = openIDObj.getUserOpenID();
                out.println("欢迎你,代号为 " + openID + " 的用户!");
                request.getSession().setAttribute("demo_openid", openID);
                // Fetch Qzone user info
                UserInfo qzoneUserInfo = new UserInfo(accessToken, openID);
                UserInfoBean userInfoBean = qzoneUserInfo.getUserInfo();
                if (userInfoBean.getRet() == 0) {
                    out.println(userInfoBean.getNickname() + "<br/>");
                    out.println(userInfoBean.getGender() + "<br/>");
                    out.println("黄钻等级: " + userInfoBean.getLevel() + "<br/>");
                    out.println("会员 : " + userInfoBean.isVip() + "<br/>");
                    out.println("黄钻会员: " + userInfoBean.isYellowYearVip() + "<br/>");
                    out.println("<image src=" + userInfoBean.getAvatar().getAvatarURL(30) + "/>
");
                    out.println("<image src=" + userInfoBean.getAvatar().getAvatarURL(50) + "/>
");
                    out.println("<image src=" + userInfoBean.getAvatar().getAvatarURL(100) + "/>
");
                } else {
                    out.println("很抱歉,我们没能正确获取到您的信息,原因是: " + userInfoBean.getMsg());
                }
                // Verify fan status
                PageFans pageFansObj = new PageFans(accessToken, openID);
                PageFansBean pageFansBean = pageFansObj.checkPageFans("97700000");
                if (pageFansBean.getRet() == 0) {
                    out.println("<p>验证您" + (pageFansBean.isFans() ? "是" : "不是") + "QQ空间97700000官方认证空间的粉丝</p>");
                } else {
                    out.println("很抱歉,我们没能正确获取到您的信息,原因是: " + pageFansBean.getMsg());
                }
                // Fetch Weibo user info (similar pattern omitted for brevity)
            }
        } catch (QQConnectException e) {
            // handle exception
        }
    }
}

After adding the above controller and proper configuration, the QQ login feature works correctly.

Other references:

Official error code documentation: http://wiki.connect.qq.com/公共返回码说明

---

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSpring MVCapi-integrationOAuthQQ Login
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.