①准备工作
I--注册QQ互联账号 -->在管理中心注册为开发者 -->创建应用 -->获取应用APP ID
II--在nat123注册应用域名
III--下载包
<!--qq互联-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
②开始实践
------------------------------------------------------------------------------------------------------------------------
1>js版本(pc上)
------------------------------------------------------------------------------------------------------------------------
详情请见:http://connect.qq.com/intro/login/jssdk-demo
例子(网站请求页和回调地址页是同一个页面)
-------------------------------------------------------------------------------------------------------------
2>sdk_client版本(mobile)【使用java后台本地代理进行跨域请求】【jsonp也可以跨域请求】
疑问:请求成功后返回的数据时html格式?非json格式
-------------------------------------------------------------------------------------------------------------
<%@ page language="java" pageEncoding="UTF-8" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Client Flow Example</title>
<script type="text/javascript" src="resources/js/jquery-2.0.3.min.js"></script>
</head>
<body>
<a href="https://graph.qq.com/oauth2.0/authorize?response_type=token&client_id=101201540&redirect_uri=http://jiasi.nat123.net/index.jsp&scope=get_user_info">qq</a>
<%--*http://jiasi.nat123.net/index.jsp?#access_token=C34A4EB530203E213DD9F5A5E9B891E6&expires_in=7776000*--%>
<a href="https://graph.qq.com/oauth2.0/me?access_token=C34A4EB530203E213DD9F5A5E9B891E6">获取openId</a>
<%--*callback( {"client_id":"101201540","openid":"AFBEA3786C12A923F66BAD7D2F87DFCC"} ); *--%>
<a href="https://graph.qq.com/user/get_user_info?access_token=C34A4EB530203E213DD9F5A5E9B891E6&oauth_consumer_key=101201540&openid=AFBEA3786C12A923F66BAD7D2F87DFCC">获取信息</a>
<%--用户信息--%>
<hr/>
<a href="https://graph.qq.com/oauth2.0/authorize?response_type=token&client_id=101201540&redirect_uri=http://jiasi.nat123.net/index.jsp&scope=get_user_info">腾讯QQ登录</a>
<img id="userImg"/>
<button type="submit" οnclick="clickQQ();"> QQ登录</button>
<span id="userName"></span>
<script type="text/javascript">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Client Flow Example</title>
<script type="text/javascript" src="resources/js/jquery-2.0.3.min.js"></script>
</head>
<body>
<a href="https://graph.qq.com/oauth2.0/authorize?response_type=token&client_id=101201540&redirect_uri=http://jiasi.nat123.net/index.jsp&scope=get_user_info">qq</a>
<%--*http://jiasi.nat123.net/index.jsp?#access_token=C34A4EB530203E213DD9F5A5E9B891E6&expires_in=7776000*--%>
<a href="https://graph.qq.com/oauth2.0/me?access_token=C34A4EB530203E213DD9F5A5E9B891E6">获取openId</a>
<%--*callback( {"client_id":"101201540","openid":"AFBEA3786C12A923F66BAD7D2F87DFCC"} ); *--%>
<a href="https://graph.qq.com/user/get_user_info?access_token=C34A4EB530203E213DD9F5A5E9B891E6&oauth_consumer_key=101201540&openid=AFBEA3786C12A923F66BAD7D2F87DFCC">获取信息</a>
<%--用户信息--%>
<hr/>
<a href="https://graph.qq.com/oauth2.0/authorize?response_type=token&client_id=101201540&redirect_uri=http://jiasi.nat123.net/index.jsp&scope=get_user_info">腾讯QQ登录</a>
<img id="userImg"/>
<button type="submit" οnclick="clickQQ();"> QQ登录</button>
<span id="userName"></span>
<script type="text/javascript">
var accessToken = window.location.hash.substring(1);//获取路径中的access_token
$.ajax({
type: 'GET',
url: 'https://graph.qq.com/oauth2.0/me?'+accessToken,
async: false,
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"callback",
success: function(o){
console.log(o);//o就是上面提到的返回包
$.ajax({
type: 'POST',
url:"/login.do",
data:{url: 'https://graph.qq.com/user/get_user_info?'+accessToken+'&oauth_consumer_key=101201540&openid='+o.openid},
async: false,
dataType: "json",
success: function(e){
alert(e.nickname);
console.log(e);
$("#userImg").attr("src",e.figureurl_qq_2);
}
});
}
});
</script>
</body>
</html>
$.ajax({
type: 'GET',
url: 'https://graph.qq.com/oauth2.0/me?'+accessToken,
async: false,
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"callback",
success: function(o){
console.log(o);//o就是上面提到的返回包
$.ajax({
type: 'POST',
url:"/login.do",
data:{url: 'https://graph.qq.com/user/get_user_info?'+accessToken+'&oauth_consumer_key=101201540&openid='+o.openid},
async: false,
dataType: "json",
success: function(e){
alert(e.nickname);
console.log(e);
$("#userImg").attr("src",e.figureurl_qq_2);
}
});
}
});
</script>
</body>
</html>
============
public class LoginServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("inter..................");
/*req.getRequestDispatcher("/WEB-INF/success.jsp").forward(req, resp);*/
String url = request.getParameter("url");
System.out.println(url);
HttpClient httpClient = new HttpClient();
// 创建GET方法的实例
GetMethod getMethod = new GetMethod(url);
// 使用系统提供的默认的恢复策略
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
try {
// 执行getMethod
int statusCode = httpClient.executeMethod(getMethod);
if (statusCode != 200) {
System.err.println("Method failed: "
+ getMethod.getStatusLine());
}
// 读取内容
byte[] responseBody = getMethod.getResponseBody();
String Msg = getMethod.getResponseBodyAsString().trim();
System.out.println("message--------------"+Msg);
// 处理内容
} catch (HttpException e) {
// 发生致命的异常,可能是协议不对或者返回的内容有问题
System.out.println();
e.printStackTrace();
} catch (IOException e) {
// 发生网络异常
e.printStackTrace();
} finally {
// 释放连接
getMethod.releaseConnection();
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("inter..................");
/*req.getRequestDispatcher("/WEB-INF/success.jsp").forward(req, resp);*/
String url = request.getParameter("url");
System.out.println(url);
HttpClient httpClient = new HttpClient();
// 创建GET方法的实例
GetMethod getMethod = new GetMethod(url);
// 使用系统提供的默认的恢复策略
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
try {
// 执行getMethod
int statusCode = httpClient.executeMethod(getMethod);
if (statusCode != 200) {
System.err.println("Method failed: "
+ getMethod.getStatusLine());
}
// 读取内容
byte[] responseBody = getMethod.getResponseBody();
String Msg = getMethod.getResponseBodyAsString().trim();
System.out.println("message--------------"+Msg);
// 处理内容
} catch (HttpException e) {
// 发生致命的异常,可能是协议不对或者返回的内容有问题
System.out.println();
e.printStackTrace();
} catch (IOException e) {
// 发生网络异常
e.printStackTrace();
} finally {
// 释放连接
getMethod.releaseConnection();
}
}
QQ第三方登陆
网站接入流程--qq登陆
===============
QQ分享空间
分享QQ好友:
------------------------=---
分享到各网站的js代码
-----------------------------------------------------------------------------------------------------------------------------------
后期修改 js版QQ登陆改为手机版本
-----------------------------------------------------------------------------------------------------------------------------------
第一种方案:页面上获取access_token和openid,后台处理用户数据
1、页面部署
+++++++++第一种情况++++++++++
----在放置qq button的页面引入js库
<script type="text/javascript" src="http://qzonestyle.gtimg.cn/qzone/openapi/qc_loader.js" data-appid="101201540" data-redirecturi="http://jiasi.nat123.net/ole-mobile/index.html" charset="utf-8" ></script>
---添加qq按钮和按钮样式
<span id="qqButton" ></span>
QC.Login({
btnId : "qqButton",//插入按钮的html标签id
size : "B_M",//按钮尺寸
scope : "get_user_info",//展示授权,全部可用授权可填 all
display : "mobile"//应用场景,可选
});
btnId : "qqButton",//插入按钮的html标签id
size : "B_M",//按钮尺寸
scope : "get_user_info",//展示授权,全部可用授权可填 all
display : "mobile"//应用场景,可选
});
---回调页面获取access_token和openid并发送请求到后台处理获得用户数据
var accessToken = window.location.hash.substring(1);//获取路径中的access_token
if(accessToken) {
$.ajax({
type: 'GET',
url: 'https://graph.qq.com/oauth2.0/me?' + accessToken,
async: false,
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback: "callback",
success: function (o) {
alert(o.openid);
$.ajax({
type: 'POST',
url: "/member/qq_login",
data: {url: 'https://graph.qq.com/user/get_user_info?' + accessToken + '&oauth_consumer_key=101201540&openid=' + o.openid},
async: false,
dataType: "json",
success: function (e) {
alert(e);
alert(e.msg);
if (e.success) {
}
}
});
}
});
}
if(accessToken) {
$.ajax({
type: 'GET',
url: 'https://graph.qq.com/oauth2.0/me?' + accessToken,
async: false,
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback: "callback",
success: function (o) {
alert(o.openid);
$.ajax({
type: 'POST',
url: "/member/qq_login",
data: {url: 'https://graph.qq.com/user/get_user_info?' + accessToken + '&oauth_consumer_key=101201540&openid=' + o.openid},
async: false,
dataType: "json",
success: function (e) {
alert(e);
alert(e.msg);
if (e.success) {
}
}
});
}
});
}
+++++++++第二种情况++++++++++
tip①不需要再页面引入js库,没有qq按钮的样式
<span id="qq_click" href="#" style="color:red;"> <img src="img/qq.png"/> </span>
注意使用<a>标签链接的形式没办法打开页面
所以使用html可识别的标签并使用jquery 点击事件打开网页
$("#qq_click").click(function(){ window.location.href = "https://graph.qq.com/oauth2.0/authorize?response_type=token&display=mobile&client_id=101201540&scope=get_user_info&redirect_uri=http://jiasi.nat123.net/ole-mobile/qq_login.html"; });
为了把QQ登录和正常登录的页面解耦,于是单独把QQ登录的处理过程另外放到一个页面去处理
<script type="text/javascript" src="js/jquery.min-2.1.1.js"></script> <script type="text/javascript"> var accessToken = window.location.hash.substring(1);//获取路径中的access_token if (accessToken) { $.ajax({ type: 'GET', url: 'https://graph.qq.com/oauth2.0/me?' + accessToken, async: false, dataType: "jsonp", jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) jsonpCallback: "callback", success: function (o) { $.ajax({ type: 'POST', url: "/ole-web/m/member/qq_login", data: {url: 'https://graph.qq.com/user/get_user_info?' + accessToken + '&oauth_consumer_key=101201540&openid=' + o.openid}, async: false, dataType: "json", success: function (e) { alert(e.msg); if (e.success) { window.localStorage.setItem("member_info", e.data.memberId + '|' + e.data.token + '|' + e.data.nickname + '|' + e.data.portrait + '|' + e.data.balance); window.location.href = "/ole-mobile/index.html#memberview"; } } }); } }); } </script>
2、后台处理用户数据
@Transactional public ThirdpartyMember getUserInfoFromQQ(String url/*HttpServletRequest request*/) { log.info("QQ第三方登录"); // String url = request.getParameter("url"); System.out.println("url:"+url); /*获取openid*/ String[] params = url.split("&"); String openid = params[OPENID_AND_VALUE_INDEX].substring(OPENID_INDEX); HttpClient httpClient = new HttpClient(); // 创建GET方法的实例 GetMethod getMethod = new GetMethod(url); // 使用系统提供的默认的恢复策略 getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); try { // 执行getMethod int statusCode = httpClient.executeMethod(getMethod); if (statusCode != 200) { System.err.println("Method failed: " + getMethod.getStatusLine()); } // 读取内容 byte[] responseBody = getMethod.getResponseBody(); String msg = getMethod.getResponseBodyAsString().trim(); if (msg != null && !msg.equals("")) { System.out.println("message----" + msg); String[] s = msg.split(","); StringBuffer sb = new StringBuffer(); for (String s1 : s) { if (s1.contains("nickname")) { sb.append(s1.split(":")[NICKNAME_INDEX].replace("\"", "")); } else if (s1.contains("figureurl")) { sb.append(","); sb.append(s1.substring(PORTRAIT_INDEX)); } if(s1.contains("figureurl_qq_1")) { sb.append(","); System.out.println("----====qq--"+s1); sb.append(s1.substring(24)); System.out.println("24---"+s1.substring(24)); break; } } String nickname = sb.toString().split(",")[0]; String portrait = sb.toString().split(",")[1]; String qq_portrait = sb.toString().split(",")[2]; System.out.println("...qq_pro--"+qq_portrait); /*保存第三方登录的用户信息 memberThirdParty 和 member 实体*/ Member member= saveThirdparty(openid, nickname, portrait, ThirdParty.QQ); ThirdpartyMember thirdpartyMember = new ThirdpartyMember(); thirdpartyMember.setNickname(nickname); thirdpartyMember.setPortrait(portrait); thirdpartyMember.setOrigin(ThirdParty.QQ); thirdpartyMember.setUsername(member.getUsername()); thirdpartyMember.setMemberId(member.getId()); System.out.println("username......"+member.getUsername()); thirdpartyMember.setPassword("third"); System.out.println("memberservice--------------"+member.getPassword()); return thirdpartyMember; } ResponseEntity<HttpEntity> hi = new ResponseEntity(responseBody, HttpStatus.OK); System.out.println("hi----"+hi.toString()); // 处理内容 // return new ResponseEntity(responseBody, HttpStatus.OK); } catch (HttpException e) { // 发生致命的异常,可能是协议不对或者返回的内容有问题 System.out.println(); e.printStackTrace(); // return new ResponseEntity("Please check your provided http address!", HttpStatus.BAD_REQUEST); } catch (IOException e) { // 发生网络异常 e.printStackTrace(); // return new ResponseEntity("Time out!", HttpStatus.BAD_GATEWAY); } finally { // 释放连接 getMethod.releaseConnection(); } return null; }
第二种方案 页面点击QQ登录 完全交给后台获取access_token、openid、处理用户数据
1、页面
用jquery构造触发点击事件 GET请求至qqRequest
2、后台处理
这是在Controller层的,可以调用上面提到的getUserInfoFromQQ
/* @RequestMapping(value = "/qqRequest",method = RequestMethod.GET)
public String qqRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
String code = request.getParameter("code");
request.setAttribute("code", code);
System.out.println("...................");
*//* 获取access_token*//*
String parames = "grant_type=authorization_code&client_id="+ CommonUtil.APP_ID +"&client_secret="+ CommonUtil.APP_KEY +"&code="+code+"&redirect_uri=" + CommonUtil.REDIRECT_URI;
String access_result = HttpRequestUtil.httpsRequest(CommonUtil.REQUEST_TOKEN_URL, "GET", parames);
if(access_result.contains("callback")){
*//*当返回的access_token是callback( {"error":100019,"error_description":"code to access token error"} )类似的数据;
* 表示获取access_token失败,需要返回点击QQ登陆页面让用户重新登陆授权
*//*
try {
response.sendRedirect("/ole-mobile/index2.html");
} catch (IOException e) {
e.printStackTrace();
}
}else {
String access_token = access_result.split("&")[0];
System.out.println("access_token="+access_token);
*//* 获取openid
* 成功后返回信息格式:callback( {"client_id":"10xxxxx18","openid":"DDxxxxxxxxxxx587"} );
*//*
String open_id = HttpRequestUtil.httpsRequest(CommonUtil.REQUEST_OPENID_URL, "GET", access_token);
System.out.println("open_id="+open_id);
if(open_id.contains("error")){
*//*当返回的open_id是callback( {"error":100007,"error_description":"param access token is wrong or lost "} );类似的数据;
* 表示获取open_id失败,需要返回点击QQ登陆页面让用户重新登陆授权
*//*
try {
response.sendRedirect("/ole-mobile/index2.html");
} catch (IOException e) {
e.printStackTrace();
}
}else {
String openId = open_id.substring(open_id.indexOf("openid")+9, open_id.lastIndexOf("\""));
String url = "https://graph.qq.com/user/get_user_info?"+access_token+"&oauth_consumer_key=101201540&openid=" + openId;
System.out.println("url:"+url);
ThirdpartyMember thirdpartyMember = memberService.getUserInfoFromQQ(url);
System.out.println("thirdpartyMember---"+thirdpartyMember.getUsername());
if (thirdpartyMember != null) {
Map<String, ThirdpartyMember> map = new HashMap<>();
map.put("thirdQuery", thirdpartyMember);
//用户第三方登录的会员名字和密码 正常登录 保存token
System.out.println("login success!");
//登录成功,保存改用户token
Token memberToken = new Token();
memberToken.setMemberId(thirdpartyMember.getMemberId());
memberToken.setToken(UUID.randomUUID().toString());
tokenRepository.save(memberToken);
//查询该会员账户余额
BigDecimal balance = accountService.findBalanceByMemberId(thirdpartyMember.getMemberId());
MemberBean memberBean = new MemberBean();
memberBean.setMobile(thirdpartyMember.getUsername());
memberBean.setNickname(thirdpartyMember.getNickname());
memberBean.setPortrait(thirdpartyMember.getPortrait());
memberBean.setMemberId(thirdpartyMember.getMemberId());
memberBean.setToken(memberToken.getToken());
memberBean.setBalance(balance);
System.out.println("json="+JSON.toJSONString(memberBean));
return new Message(true,"login success!",memberBean).toJson();
}
}
}
return new Message(true,"login fail!").toJson();
}*/
public String qqRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
String code = request.getParameter("code");
request.setAttribute("code", code);
System.out.println("...................");
*//* 获取access_token*//*
String parames = "grant_type=authorization_code&client_id="+ CommonUtil.APP_ID +"&client_secret="+ CommonUtil.APP_KEY +"&code="+code+"&redirect_uri=" + CommonUtil.REDIRECT_URI;
String access_result = HttpRequestUtil.httpsRequest(CommonUtil.REQUEST_TOKEN_URL, "GET", parames);
if(access_result.contains("callback")){
*//*当返回的access_token是callback( {"error":100019,"error_description":"code to access token error"} )类似的数据;
* 表示获取access_token失败,需要返回点击QQ登陆页面让用户重新登陆授权
*//*
try {
response.sendRedirect("/ole-mobile/index2.html");
} catch (IOException e) {
e.printStackTrace();
}
}else {
String access_token = access_result.split("&")[0];
System.out.println("access_token="+access_token);
*//* 获取openid
* 成功后返回信息格式:callback( {"client_id":"10xxxxx18","openid":"DDxxxxxxxxxxx587"} );
*//*
String open_id = HttpRequestUtil.httpsRequest(CommonUtil.REQUEST_OPENID_URL, "GET", access_token);
System.out.println("open_id="+open_id);
if(open_id.contains("error")){
*//*当返回的open_id是callback( {"error":100007,"error_description":"param access token is wrong or lost "} );类似的数据;
* 表示获取open_id失败,需要返回点击QQ登陆页面让用户重新登陆授权
*//*
try {
response.sendRedirect("/ole-mobile/index2.html");
} catch (IOException e) {
e.printStackTrace();
}
}else {
String openId = open_id.substring(open_id.indexOf("openid")+9, open_id.lastIndexOf("\""));
String url = "https://graph.qq.com/user/get_user_info?"+access_token+"&oauth_consumer_key=101201540&openid=" + openId;
System.out.println("url:"+url);
ThirdpartyMember thirdpartyMember = memberService.getUserInfoFromQQ(url);
System.out.println("thirdpartyMember---"+thirdpartyMember.getUsername());
if (thirdpartyMember != null) {
Map<String, ThirdpartyMember> map = new HashMap<>();
map.put("thirdQuery", thirdpartyMember);
//用户第三方登录的会员名字和密码 正常登录 保存token
System.out.println("login success!");
//登录成功,保存改用户token
Token memberToken = new Token();
memberToken.setMemberId(thirdpartyMember.getMemberId());
memberToken.setToken(UUID.randomUUID().toString());
tokenRepository.save(memberToken);
//查询该会员账户余额
BigDecimal balance = accountService.findBalanceByMemberId(thirdpartyMember.getMemberId());
MemberBean memberBean = new MemberBean();
memberBean.setMobile(thirdpartyMember.getUsername());
memberBean.setNickname(thirdpartyMember.getNickname());
memberBean.setPortrait(thirdpartyMember.getPortrait());
memberBean.setMemberId(thirdpartyMember.getMemberId());
memberBean.setToken(memberToken.getToken());
memberBean.setBalance(balance);
System.out.println("json="+JSON.toJSONString(memberBean));
return new Message(true,"login success!",memberBean).toJson();
}
}
}
return new Message(true,"login fail!").toJson();
}*/