ssm项目之第三方QQ登陆

首先你要注册成为开发者https://connect.qq.com/

注册的过程中要手持身份证拍照上传的

然后创建应用,你没有域名也没有关系的,审核不通过也没事,我们主要使用到APP ID和APP KEY,还有回调地址一定要有!!!

我已经创建好了,因为我是本地测试使用的,所以只能使用自己的QQ进行授权登陆,创建好了审核通过不通过都会有APP ID和APP Key,在填写网站地址的时候一定要http开头,我就直接写了我网站首页访问的地址,但是在写回调地址的时候不能写localhost我要把它改写成127.0.0.1才能通过,其他的就随便填写就行。

接着下载相应的SDK,我的是java版本的SDK下载地址http://wiki.open.qq.com/wiki/website/SDK%E4%B8%8B%E8%BD%BD,里面就有相应的代码根据使用说明修改就行。

改写成在maven+ssm项目中使用

首先在pom.xml引入相关依赖jar

<dependency>
   <groupId>net.gplatform</groupId>
   <artifactId>Sdk4J</artifactId>
   <version>2.0</version>
</dependency>

然后修改qqconnectconfig.properties文件中的几个字段,app_ID和app_KEY就是创建应用的时候自动分配给你了的,直接复制过来,redirect_URI就是创建应用的时候自己填写的回调地址,这里我把scope自动也删了后面的,因为我只需要获取用户信息所以只剩一个就行。

接着看controller的代码


package com.qq.connect.demo2;


import com.qq.connect.QQConnectException;
import com.qq.connect.api.OpenID;
import com.qq.connect.api.qzone.UserInfo;
import com.qq.connect.javabeans.AccessToken;
import com.qq.connect.javabeans.qzone.UserInfoBean;
import com.qq.connect.oauth.Oauth;
import com.qq.connect.utils.IpHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
@RequestMapping("qqlogin")
public class MvcQQLoginController {

    private static final String QQ_ACCESS_TOKEN = "accessToken";
    private static final String QQ_OPENID = "openid";

    private Logger logger = LoggerFactory.getLogger(MvcQQLoginController.class);

    /**
     * 请求QQ的登陆界面
     *
     * @param request request请求
     * @return QQ登陆页面
     */
    @RequestMapping(value = "login", method = {RequestMethod.GET})
    public String toQQLoginPage(HttpServletRequest request) {
        String authorizeURL = null;
        try {
            authorizeURL = new Oauth().getAuthorizeURL(request);
        } catch (QQConnectException e) {
            logger.error("QQ登陆错误:", e);
        }
        authorizeURL = new StringBuffer("redirect:").append(authorizeURL).toString();
        logger.info("请求QQ登陆地址:{}", authorizeURL);
        return authorizeURL;
    }

    /**
     * FIXME 实际网路请求部分代码可以自己使用httpclient类来进行实现
     * 跳转到登陆成功页面
     *
     * @return 登陆成功页面
     */
    @RequestMapping(value = "/callback", method = {RequestMethod.GET})
    public String toLoginSuccessPage(HttpServletRequest request, Model model) throws QQConnectException {
        //注意:accessToken,openID是最重要的两个东西,要控制好
        HttpSession session = request.getSession();
        AccessToken accessTokenObj = null;
        String accessToken = null;
        String openID = null;
        try {
           
            //1.发出第一次请求获取access_token
            //用户已经登陆过
            if (session.getAttribute(QQ_ACCESS_TOKEN) != null && session.getAttribute(QQ_OPENID) != null) {
                accessToken = String.valueOf(session.getAttribute(QQ_ACCESS_TOKEN));
                openID = String.valueOf(session.getAttribute(QQ_OPENID));
            } else {
                //用户第一次登陆
                if ("".equals(accessToken)) {
                    //第一次登陆非法请求
                    logger.warn("[ip:{}]请停止当前非法请求!", IpHelper.getIpAddr(request));
                    return "redirect:/fail";
                } else {
                    //第一次合法登陆
                    //在回调的地址栏中通过Authorization Code获取Access Token,这里工具类进行一步封装了
                    accessTokenObj = new Oauth().getAccessTokenByRequest(request);
                    accessToken = accessTokenObj.getAccessToken();
                    OpenID openIDObj = new OpenID(accessToken);
                    //2.发出第二次请求获取openid
                  
                    openID = openIDObj.getUserOpenID();
                    session.setAttribute("accessToken", accessToken);
                    session.setAttribute("openid", openID);
                }
            }
            UserInfo qzoneUserInfo = new UserInfo(accessToken, openID);
            //3.发出第三次请求获取用户信息 userInfoBean
           
            //返回用户信息
            UserInfoBean userInfoBean = qzoneUserInfo.getUserInfo();
            model.addAttribute("userInfoBean", userInfoBean);

        } catch (QQConnectException e) {
            logger.error("跳转到回调地址失败:", e);
            return "fail";
        }
        return "success";
    }


    /**
     * 注销QQ登陆操作
     *
     * @param request 请求request
     * @return 返回登陆页面
     */
    @RequestMapping(value = "/out", method = {RequestMethod.GET})
    public String toLoutoutPage(HttpServletRequest request) {
        request.getSession().removeAttribute(QQ_ACCESS_TOKEN);
        request.getSession().removeAttribute(QQ_OPENID);
        return "redirect:/index.jsp";
    }


}

使用到的工具类

/*
 * Copyright 2018 KiWiPeach.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qq.connect.utils;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.logging.Logger;


public class IpHelper {
    private static final Logger logger = Logger.getLogger("IpHelper");

    private static String LOCAL_IP_STAR_STR = "192.168.";

    static {
        String ip = null;
        String hostName = null;
        try {
            hostName = InetAddress.getLocalHost().getHostName();
            InetAddress ipAddr[] = InetAddress.getAllByName(hostName);
            for (int i = 0; i < ipAddr.length; i++) {
                ip = ipAddr[i].getHostAddress();
                if (ip.startsWith(LOCAL_IP_STAR_STR)) {
                    break;
                }
            }
            if (ip == null) {
                ip = ipAddr[0].getHostAddress();
            }

        } catch (UnknownHostException e) {
            logger.severe("IpHelper error.");
            e.printStackTrace();
        }

        LOCAL_IP = ip;
        HOST_NAME = hostName;

    }

    /** 系统的本地IP地址 */
    public static final String LOCAL_IP;

    /** 系统的本地服务器名 */
    public static final String HOST_NAME;

    /**
     * <p>
     *  获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。
     *  但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了,如果通过了多级反向代理的话,
     *  X-Forwarded-For的值并不止一个,而是一串IP值, 究竟哪个才是真正的用户端的真实IP呢?
     *  答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
     *  例如:X-Forwarded-For:192.168.1.110, 192.168.1.120,
     *  192.168.1.130, 192.168.1.100 用户真实IP为: 192.168.1.110
     *  </p>
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (ip.equals("127.0.0.1")) {
                /** 根据网卡取本机配置的IP */
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                    ip = inet.getHostAddress();
                } catch (UnknownHostException e) {
                    logger.severe("IpHelper error." + e.toString());
                }
            }
        }
        /**
         * 对于通过多个代理的情况, 第一个IP为客户端真实IP,多个IP按照','分割 "***.***.***.***".length() =
         * 15
         */
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return ip;
    }

}

前端首页代码

<%--

  Date: 12-12-4
  Time: 上午10:26
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title></title>
  </head>
  <body>
  <a href="/qqlogin/login"><img src="images/Connect_logo_1.png"/>QQ登录</a>
  <h3>
    <p>登陆原理:</p>
  </h3>
  <h5>
    <p>第一步: 请求QQ登陆地址:redirect:https://graph.qq.com/oauth2.0/authorize?client_id=101465199&redirect_uri=http://localhost:8080/afterlogin.do&response_type=code&state=cc86ad8159bf700ef45570777dc038ab&scope=get_user_info,add_topic,add_one_blog,add_album,upload_pic,list_album,add_share,check_page_fans,add_t,add_pic_t,del_t,get_repost_list,get_info,get_other_info,get_fanslist,get_idollist,add_idol,del_ido,get_tenpay_addr</p>
    <p>第二步:用户在客户端(PC端,手机端)点击授权按钮</p>
    <img src="images/qq-loginpage.png" style="height: 100px;width: 300px;"/>
    <p>第三步:腾讯统一用户认证中心,会去请求我们申请的回调地址:http://localhost:8080/afterlogin.do</p>
    <p>第四步:使用client_id,client_secret(这两个信息一定要保管好)..等去请求认证中心,认证中心返回access_token和refresh_token</p>
    <p>第五部:将上一步认证中心返回的access_token和refresh_token,再次请求请求认证中心,返回openid</p>
    <p>第六步:将第五步的openid和第四部的access_token再去请求用户信息接口,腾讯将返回用户信息给用户,此时已经QQ认证完毕,目的达成了。</p>
  </h5>
  </body>
</html>

授权成功后的前端代码


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>QQ登陆成功页面</title>
</head>
<body style="text-align: center">
<div>
    <table>
        <tr>
            <td>昵称</td>
            <td>${requestScope.userInfoBean.nickname}</td>
        </tr>
        <tr>
            <td>头像</td>
            <td><image src="${requestScope.userInfoBean.avatar.avatarURL50}"></image></td>
        </tr>
            <td>性别</td>
            <td>${requestScope.userInfoBean.gender}</td>
        </tr>
        <tr>
            <td>accessToken</td>
            <td>${sessionScope.accessToken}</td>
        </tr>
        <tr>
            <td>openid</td>
            <td>${sessionScope.openid}</td>
        </tr>
        <tr>
            <td>province</td>
            <td>${sessionScope.userInfoBean.province}</td>
        </tr>
        <tr>
            <td>city</td>
            <td>${sessionScope.userInfoBean.city}</td>
        </tr>
       <tr>
            <td>year</td>
            <td>${sessionScope.userInfoBean.year}</td>
        </tr>

    </table>
</div>
<div>
    <a href="/qqlogin/out">注销当前用户</a>
    <button>获取Qzone的昵称</button>
    <button>是否为认证空间的粉丝</button>
    <button>微博的昵称等信息</button>
</div>

</body>
</html>

我是使用idea运行代码,所以在配置tomcat的时候要把localhost改成127.0.0.1,因为我回调地址那里是使用到127.0.0.1刚开始我以为它自己会知道这两个是等同的,但是事实是他不懂,所以我们还是帮他一把吧。

然后我们可以运行来看看了

直接运行idea里面的tomcat就自动跳转到首页

然后点击QQ登陆,来到我们熟悉的授权页面,然后授权

授权完成之后

这就完成了通过QQ来登陆了.

完整代码:https://github.com/ChenLaiHong/QQ_Login.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值