本文用项目框架为spring boot
本文旨在简介QQ第三方登陆的主要步骤,
网站QQ第三方登陆需要几个条件
1.拥有QQ开放平台
如果没有的话需要到https://connect.qq.com/申请
2.进入开放平台,并在网站应用下创建相应的应用
QQ官方文档
http://wiki.connect.qq.com/%E7%BD%91%E7%AB%99%E5%BA%94%E7%94%A8%E6%8E%A5%E5%85%A5%E6%B5%81%E7%A8%8B
本文相关代码的来源http://qzonestyle.gtimg.cn/qzone/vas/opensns/res/doc/qqConnect_Server_SDK_java_v2.0.zip
整个过程有以下步骤
1.生成QQ登陆页面url,并跳转至该页面
2.拿到浏览器url的code和state,通过该code和state获取access_token和openid
3.通过access_token和openid获取登陆用户信息
下面是主要代码:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>oauth.qq</groupId>
<artifactId>oauth.qq</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>www</name>
<description>Third party landing of oauth QQ</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--在tomcat中运行时,取消该注释-->
<!--<scope>provided</scope>-->
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<!-- qq第三方登陆 -->
<dependency>
<groupId>net.gplatform</groupId>
<artifactId>Sdk4J</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<finalName>ROOT</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- maven tomcat 插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<path>/</path>
<port>8888</port>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
</project>
qqconnectconfig.properties
app_ID=
app_KEY=
redirect_URI=
scope=get_user_info
baseURL=https://graph.qq.com/
getUserInfoURL=https://graph.qq.com/user/get_user_info
accessTokenURL=https://graph.qq.com/oauth2.0/token
authorizeURL=https://graph.qq.com/oauth2.0/authorize
getOpenIDURL=https://graph.qq.com/oauth2.0/me
version=2.0.0.0
//OauthController
/**
* 微信服务controller
* @author Lichenyi
* @date 2017-7-5
*/
@Controller
@RequestMapping("/oauth")
public class OauthController {
private Logger logger = LogManager.getLogger(getClass());
@Autowired
private IQQService qqService;
/**
* 跳转QQ登陆页面
* @param request
* @param response
*/
@GetMapping("/qq/login")
@ResponseBody
public void qqLogin(HttpServletRequest request, HttpServletResponse response){
response.setContentType("text/html;charset=utf-8");
try {
String url = new Oauth().getAuthorizeURL(request);
logger.info(String.format("qq sendRedirect --> %s", url));
response.sendRedirect(new Oauth().getAuthorizeURL(request));
} catch (QQConnectException | IOException e) {
e.printStackTrace();
}
}
/**
* 获取QQ账号信息, 最终返回的是狮吼平台的用户数据
* @param request 参数 code 和 state
* @param response
* @return
*/
@GetMapping("/qq/userInfo")
@ResponseBody
public ResponseEntity<Result> getQQUserInfo(HttpServletRequest request, HttpServletResponse response){
response.setContentType("text/html;charset=utf-8");
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON_UTF8)
.body(Result.build().content(qqService.getUserInfo(request)));
}
}
service的接口和实现类
/**
* @author lichenyi
* @date 2017-7-6
*/
public interface IQQService {
Object getUserInfo(HttpServletRequest request);
}
/**
* @author Lichenyi
* @date 2017-7-5
*/
@SuppressWarnings("all")
@Service("IQQService")
public class QQService implements IQQService {
private Logger logger = LogManager.getLogger(getClass());
@Value("${qq.open.me}")
private String meUrl;
@Autowired
private RestTemplate restTemplate;
/**
* 获取用户信息
*
* @param code
* @return
*/
@Override
public Object getUserInfo(HttpServletRequest request) {
try {
request.getSession().setAttribute("qq_connect_state", request.getParameter("state"));
AccessToken accessTokenObj = (new Oauth()).getAccessTokenByRequest(request);
String accessToken = null,
openID = null;
long tokenExpireIn = 0L;
if (accessTokenObj.getAccessToken().equals("")) {
logger.info("没有获取到响应参数");
return "没有获取到响应参数";
} else {
//获取token
accessToken = accessTokenObj.getAccessToken();
tokenExpireIn = accessTokenObj.getExpireIn();
/*
//通过自我调用QQ的方法获取openid和unionid
JSONObject jsonObject = getQQMe(accessToken);
String openid = jsonObject.getString("openid");
String unionid = jsonObject.getString("unionid");
*/
//获取个人的头像昵称等信息
//获取openid
OpenID openIDObj = new OpenID(accessToken);
openID = openIDObj.getUserOpenID();
//获取用户信息
UserInfo qzoneUserInfo = new UserInfo(accessToken, openID);
UserInfoBean userInfoBean = (UserInfoBean) qzoneUserInfo.getUserInfo();
com.qq.connect.utils.json.JSONObject jsonUserInfoBean = new com.qq.connect.utils.json.JSONObject(userInfoBean);
//以下两行代码可以省略直接返回userInfoBean,我这里是想把openID也添加到返回结果中
QQUserInfoBeanx result = new QQUserInfoBeanx(jsonUserInfoBean);
result.setOpenId(openID);
return result;
}
} catch (QQConnectException e) {
e.printStackTrace();
}
return null;
}
private JSONObject getQQMe(String accessToken){
String url = String.format(meUrl, accessToken);
String string = restTemplate.getForObject(url, String.class);
String jsonStr = string.substring(string.indexOf("{"), string.indexOf("}")+1);
JSONObject jsonObject = (JSONObject) JSON.parse(jsonStr);
return jsonObject;
}
}
QQ第三方登陆有个很坑的地方就是如果要获取unionid需要用这个接口,而且必须要加上unionid=1这个参数,返回结果是一个callback();内容中有client_id、openid、unionid这三个值
https://graph.qq.com/oauth2.0/me?unionid=1&access_token=
项目地址:https://github.com/lichenyigit/oauth.qq.git