我们在讲qq登陆的集成。

首先qq登陆的注册问题,我们需要去qq互联申请账号,

地址:https://connect.qq.com/index.html

注册后在应用管理创建网站应用,设置回调地址:

获取app ID,app Key

注意就算审核不通过,你也可以登陆你自己的账号,测试是不会收到影响的

前期的东西都准备齐了现在我们就开始集成。

这是资料文档的地址一定要看完:

http://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0

下面是文档中的基本操作顺序:

看完文档后就是代码集成部分:

maven 依赖:

<dependency><groupId>commons-httpclient</groupId><artifactId>commons-httpclient</artifactId><version>3.0.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-io</artifactId><version>1.3.2</version>
</dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.4</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.3.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.38</version></dependency>

前端放置QQ登陆的按钮,login.html:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录页面</title>
</head>
<body>
<a href="/login/qq">QQ登陆</a>
</body>
</html>

这个是登陆成功以后跳转的页面,index.html:

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>测试页面</title>
</head>
<body>
<span>欢迎:</span>
<p th:text="${nickName}"></p>
</body>
</html>

下面是application.properties,配置文件:


########qq的登陆密钥#####
oauth.qq.client_id=
oauth.qq.client_secret=
oauth.qq.redirect_uri=http://zhy.nat100.top/authorize/qq
oauth.qq.code_callback_uri=https://graph.qq.com/oauth2.0/authorize
oauth.qq.access_token_callback_uri=https://graph.qq.com/oauth2.0/token
oauth.qq.openid_callback_uri=https://graph.qq.com/oauth2.0/me
oauth.qq.user_info_callback_uri=https://graph.qq.com/user/get_user_info

下面是util类,HttpsUtils :

package com.haihua.haihua.Utils;import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;/*** Created by xslde on 2018/7/21*/
public class HttpsUtils {private static PoolingHttpClientConnectionManager connMgr;private static RequestConfig requestConfig;private static final int MAX_TIMEOUT = 7000;private static final Logger logger = LoggerFactory.getLogger(HttpsUtils.class);static {// 设置连接池connMgr = new PoolingHttpClientConnectionManager();// 设置连接池大小connMgr.setMaxTotal(100);connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());// Validate connections after 1 sec of inactivityconnMgr.setValidateAfterInactivity(1000);RequestConfig.Builder configBuilder = RequestConfig.custom();// 设置连接超时configBuilder.setConnectTimeout(MAX_TIMEOUT);// 设置读取超时configBuilder.setSocketTimeout(MAX_TIMEOUT);// 设置从连接池获取连接实例的超时configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT);requestConfig = configBuilder.build();}/*** 发送 GET 请求(HTTP),不带输入数据** @param url* @return*/public static String doGet(String url) {return doGet(url, new HashMap<String, Object>());}/*** 发送 GET 请求(HTTP),K-V形式** @param url* @param params* @return*/public static String doGet(String url, Map<String, Object> params) {String apiUrl = url;StringBuffer param = new StringBuffer();int i = 0;for (String key : params.keySet()) {if (i == 0)param.append("?");elseparam.append("&");param.append(key).append("=").append(params.get(key));i++;}apiUrl += param;String result = null;HttpClient httpClient = null;if (apiUrl.startsWith("https")) {httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();} else {httpClient = HttpClients.createDefault();}try {HttpGet httpGet = new HttpGet(apiUrl);HttpResponse response = httpClient.execute(httpGet);HttpEntity entity = response.getEntity();if (entity != null) {InputStream instream = entity.getContent();result = new BufferedReader(new InputStreamReader(instream)).lines().collect(Collectors.joining(System.lineSeparator()));}} catch (IOException e) {logger.error(e.getMessage());}return result;}/*** 发送 POST 请求(HTTP),不带输入数据** @param apiUrl* @return*/public static String doPost(String apiUrl) {return doPost(apiUrl, new HashMap<String, Object>());}/*** 发送 POST 请求,K-V形式** @param apiUrl API接口URL* @param params 参数map* @return*/public static String doPost(String apiUrl, Map<String, Object> params) {CloseableHttpClient httpClient = null;if (apiUrl.startsWith("https")) {httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();} else {httpClient = HttpClients.createDefault();}String httpStr = null;HttpPost httpPost = new HttpPost(apiUrl);CloseableHttpResponse response = null;try {httpPost.setConfig(requestConfig);List<NameValuePair> pairList = new ArrayList<>(params.size());for (Map.Entry<String, Object> entry : params.entrySet()) {NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString());pairList.add(pair);}httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset.forName("UTF-8")));response = httpClient.execute(httpPost);HttpEntity entity = response.getEntity();httpStr = EntityUtils.toString(entity, "UTF-8");} catch (IOException e) {logger.error(e.getMessage());} finally {if (response != null) {try {EntityUtils.consume(response.getEntity());} catch (IOException e) {logger.error(e.getMessage());}}}return httpStr;}/*** 发送 POST 请求,JSON形式** @param apiUrl* @param json   json对象* @return*/public static String doPost(String apiUrl, Object json) {CloseableHttpClient httpClient = null;if (apiUrl.startsWith("https")) {httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();} else {httpClient = HttpClients.createDefault();}String httpStr = null;HttpPost httpPost = new HttpPost(apiUrl);CloseableHttpResponse response = null;try {httpPost.setConfig(requestConfig);StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");// 解决中文乱码问题stringEntity.setContentEncoding("UTF-8");stringEntity.setContentType("application/json");httpPost.setEntity(stringEntity);response = httpClient.execute(httpPost);HttpEntity entity = response.getEntity();httpStr = EntityUtils.toString(entity, "UTF-8");} catch (IOException e) {logger.error(e.getMessage());} finally {if (response != null) {try {EntityUtils.consume(response.getEntity());} catch (IOException e) {logger.error(e.getMessage());}}}return httpStr;}/*** 创建SSL安全连接** @return*/private static SSLConnectionSocketFactory createSSLConnSocketFactory() {SSLConnectionSocketFactory sslsf = null;try {SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {return true;}}).build();sslsf = new SSLConnectionSocketFactory(sslContext, new HostnameVerifier() {@Overridepublic boolean verify(String arg0, SSLSession arg1) {return true;}});} catch (GeneralSecurityException e) {logger.error(e.getMessage());}return sslsf;}
}

下面是接受properties值的实体类和config类:(注意实体我是用了Lombok的Data属性,你可以自己手动getter,setter)

package com.haihua.haihua.properties;import lombok.Data;@Data
public class QQProperties {private String client_id;private String client_secret;private String redirect_uri;private String code_callback_uri;private String access_token_callback_uri;private String openid_callback_uri;private String user_info_callback_uri;}
package com.haihua.haihua.properties;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component//注入到spring容器,方便后面使用
@ConfigurationProperties(prefix = "oauth")//对应application.yml中,oauth下参数
public class OAuthProperties {//获取applicaiton.yml下qq下所有的参数private QQProperties qq = new QQProperties();public QQProperties getQQ() {return qq;}public void setQQ(QQProperties qq) {this.qq = qq;}
}

下面是接受qq信息的实体类 ,QQDTO.java:

package com.haihua.haihua.entity;import lombok.Data;@Data
public class QQDTO {private String ret;        //返回码private String msg;        //如果ret<0,会有相应的错误信息提示,返回数据全部用UTF-8编码。private String nickname;             //用户在QQ空间的昵称。private String figureurl;              //大小为30×30像素的QQ空间头像URL。private String figureurl_1;                //大小为50×50像素的QQ空间头像URL。private String figureurl_2;                //大小为100×100像素的QQ空间头像URL。private String figureurl_qq_1;                   //大小为40×40像素的QQ头像URL。private String figureurl_qq_2;                   //大小为100×100像素的QQ头像URL。需要注意,不是所有的用户都拥有QQ的100x100的头像,但40x40像素则是一定会有。private String gender;           //性别。 如果获取不到则默认返回"男"private String is_yellow_vip;                  //标识用户是否为黄钻用户(0:不是;1:是)。private String vip;        //标识用户是否为黄钻用户(0:不是;1:是)private String yellow_vip_level;                     //黄钻等级private String level;          //黄钻等级private String is_yellow_year_vip;                       //标识是否为年费黄钻用户(0:不是; 1:是)
}

下面是接受qq应用的实体类 ,QQDTO.java:

package com.haihua.haihua.entity;import lombok.Data;@Data
public class QQOpenidDTO {private String openid;private String client_id;
}

下面则是控制类,LoginAction.java:

package com.haihua.haihua.controller;import com.google.gson.Gson;
import com.haihua.haihua.Utils.HttpsUtils;
import com.haihua.haihua.entity.QQDTO;
import com.haihua.haihua.entity.QQOpenidDTO;
import com.haihua.haihua.properties.OAuthProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;/*** Created by xslde on 2018/7/21*/
@Controller
public class LoginAction {private Logger logger = LoggerFactory.getLogger(getClass());@GetMapping("/login")public String login() {return "login";}@Autowiredprivate OAuthProperties oauth;//QQ登陆对外接口,只需将该接口放置html的a标签href中即可@GetMapping("/login/qq")public void loginQQ(HttpServletResponse response) {try {response.sendRedirect(oauth.getQQ().getCode_callback_uri() + //获取code码地址"?client_id=" + oauth.getQQ().getClient_id()//appid+ "&state=" + UUID.randomUUID() + //这个说是防攻击的,就给个随机uuid吧"&redirect_uri=" + oauth.getQQ().getRedirect_uri() +//这个很重要,这个是回调地址,即就收腾讯返回的code码"&response_type=code");//授权模式,授权码模式} catch (IOException e) {e.printStackTrace();}}//接收回调地址带过来的code码@GetMapping("/authorize/qq")public String authorizeQQ(Map<String, String> msg, String code,Model model) {HashMap<String, Object> params = new HashMap<>();params.put("code", code);params.put("grant_type", "authorization_code");params.put("redirect_uri", oauth.getQQ().getRedirect_uri());params.put("client_id", oauth.getQQ().getClient_id());params.put("client_secret", oauth.getQQ().getClient_secret());//获取access_token如:access_token=9724892714FDF1E3ED5A4C6D074AF9CB&expires_in=7776000&refresh_token=9E0DE422742ACCAB629A54B3BFEC61FFString result = HttpsUtils.doGet(oauth.getQQ().getAccess_token_callback_uri(), params);//对拿到的数据进行切割字符串String[] strings = result.split("&");//切割好后放进mapMap<String, String> reulsts = new HashMap<>();for (String str : strings) {String[] split = str.split("=");if (split.length > 1) {reulsts.put(split[0], split[1]);}}//到这里access_token已经处理好了//下一步获取openid,只有拿到openid才能拿到用户信息String openidContent = HttpsUtils.doGet(oauth.getQQ().getOpenid_callback_uri() + "?access_token=" + reulsts.get("access_token"));//接下来对openid进行处理//截取需要的那部分json字符串String openid = openidContent.substring(openidContent.indexOf("{"), openidContent.indexOf("}") + 1);Gson gson = new Gson();//将返回的openid转换成DTOQQOpenidDTO qqOpenidDTO = gson.fromJson(openid, QQOpenidDTO.class);//接下来说说获取用户信息部分//登陆的时候去数据库查询用户数据对于openid是存在,如果存在的话,就不用拿openid获取用户信息了,而是直接从数据库拿用户数据直接认证用户,// 否则就拿openid去腾讯服务器获取用户信息,并存入数据库,再去认证用户//下面关于怎么获取用户信息,并登陆params.clear();params.put("access_token", reulsts.get("access_token"));//设置access_tokenparams.put("openid", qqOpenidDTO.getOpenid());//设置openidparams.put("oauth_consumer_key", qqOpenidDTO.getClient_id());//设置appidString userInfo = HttpsUtils.doGet(oauth.getQQ().getUser_info_callback_uri(), params);QQDTO qqDTO = gson.fromJson(userInfo, QQDTO.class);//这里拿用户昵称,作为用户名,openid作为密码(正常情况下,在开发时候用openid作为用户名,再自己定义个密码就可以了)try {logger.info("nickName:"+qqDTO.getNickname()+";opendId:"+qqOpenidDTO.getOpenid());model.addAttribute("nickName",qqDTO.getNickname());} catch (Exception e) {msg.put("msg", "第三方登陆失败,请联系管理!");logger.error(e.getMessage());return "login";}return "index";}}

实现后请求域名加 qq/login

点击QQ登录以后跳转:

点击即可登录:

这就完成了qq登录的基本功能。

第三方登陆(二)QQ登陆相关推荐

  1. 测试案例设计-账户名登陆、QQ登陆、测试水杯

    目录 账户名和密码登陆测试 QQ登陆的测试用例 百度云盘APP核心功能需求分析 账户名和密码登陆测试 首先根据登陆这个需求的流程来分析:输入账户名.密码.验证码的测试点 输入正确的账户名.密码.验证码 ...

  2. qq登陆inc.php,登陆验证 qq登陆验证 php 登陆验证

    用户登录验证脚本,Chkpwd.asp '=======用户登录验证脚本======= '如果尚未定义Passed对象,则将其定义为false,表示没有通过验证 If IsEmpty(Session( ...

  3. 免注册登陆以及QQ登陆

    (一)QQ登陆 (1)基本调用过程分析: ①生成授权连接,需要配置回调地址 https://graph.qq.com/oauth2.0/authorize?response_type=code& ...

  4. 第三方登录(QQ登陆)实现

    废话少说,咱们直奔主题! 对于整个流程的详细文档可以到QQ互联官网([http://wiki.connect.qq.com])查看,我这里就简单地进行描述,主要是分析代码的实现过程. 本次流程是基于C ...

  5. web开发第三方登陆之QQ登陆

    开发准备 1,一个线上的可以通过域名访问的已经备案的拥有文件控制权限的web站点 2,在QQ互联https://connect.qq.com创建一个网站应用,获得APPID,APPKEY和填写授权回调 ...

  6. 第三方登陆--QQ登陆

    QQ登录,亦即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录网站/移动端. 在进行QQ登陆的实现之前,我们需要根据QQ互联的要求,进行相关的操作: 1.成为开 ...

  7. QQ登陆第三方Demo(QQ互联)

    项目需要做QQ.微博等登陆第三方的功能,第一次接触,虽然官网上有sdk,接口写的很好,调用即可,但是没有文档,看着头疼就自己写了 步骤不多说: 一.申请AppID和AppKey,申请地址:点击打开链接 ...

  8. 五、Springboot 整合Shiro---03认证---第三方QQ登陆

    本章节基于:四.Springboot 整合Shiro---02认证---记住我 在开始之前,先要理解一下oauth2: 推荐去看一下(六.授权码模式):阮一峰讲解的oauth2 下面附上一张阮一峰博客 ...

  9. 第三方登陆——QQ登陆详解

    申请地址 QQ互联:https://connect.qq.com/index.html 腾讯开放平台:https://open.tencent.com/ 注册账号 登陆 进入QQ互联,点击登陆 资料填 ...

最新文章

  1. 基于mybatis声明SQL Session对象
  2. Python处理大数据
  3. [20170513]update结果集.txt
  4. mysql全局权限账户%登录不上ERROR 1045 (28000): Access denied for user #39;mhz#39;@#39;localhost#39; (using ...
  5. UA SIE545 优化理论基础4 对偶理论简介3 强对偶
  6. 数据驱动车主 App 产品优化,轻松搞定用户体验与转化
  7. 【渝粤题库】陕西师范大学164117 企业组网技术 作业 (高起专)
  8. linux双ip备份,LINUX系统的双网卡双IP(双链路)实现方式
  9. DOM-动态操作心得
  10. C# Winform 窗体美化(八、Icon)
  11. 顶级公司在做数据挖掘,却忽略了数据管理平台,这个知识不得不看
  12. java如何实现计算数据的录入_Java如何实现键盘数据的录入?
  13. 如果华为完全没办法买到芯片,是否可以尝试做无芯手机?
  14. 人工智能平台 H2O.ai
  15. 室内定位无GPS怎么办?阿木送来解决方案~
  16. 查询2021高考成绩位次,2021年江苏高考位次表及高考个人成绩排名查询
  17. SQLI DUMB SERIES-2
  18. 我想深入学习Go语言
  19. unraid 文件服务器,unraid使用记录3——黑群晖安装(包含文件)
  20. 多方协同,华为云IoT ,加速批量交付

热门文章

  1. iPhone 隐藏底部 “Dock栏 ”教程
  2. Armbian 笔记五_如何在 Armbian 上安装 xfce4 桌面
  3. 使用Gitee+Hexo搭建高速稳定的个人博客
  4. c语言判断化学方程式,热化学方程式计算方法和书写
  5. APP漏洞扫描器之本地拒绝服务检测详解
  6. 详解,python求矩阵的秩,你肯定能看懂
  7. 铁电存储器FRAM的优劣势
  8. 01 计算机、程序和Java概述
  9. 企业服务总线--解决方案剖析,第 1 部分: 企业服务总线的基本概念
  10. 推荐一个无版权图片网站