第三方登录之微信登录流程和代码
微信登录:
在第三方注册一个账号;访问地址,获取code,再通过code获取at,在通过at调用地址获取资源.
0:域名的本地映射,在微信开放平台注册一个账号,进行开发者的认证.
1,请求code
参数说明
参数 是否必须 说明
appid 是 应用唯一标识
redirect_uri 是 请使用urlEncode对链接进行处理
response_type 是 填code
scope 是 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即
state 否 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验
返回说明
用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数
redirect_uri?code=CODE&state=STATE
若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数
redirect_uri?state=STATE
.第二步:通过code获取access_token
通过code获取access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明
参数 是否必须 说明
appid 是 应用唯一标识,在微信开放平台提交应用审核通过后获得
secret 是 应用**AppSecret,在微信开放平台提交应用审核通过后获得
code 是 填写第一步获取的code参数
grant_type 是 填authorization_code
返回说明
正确的返回:
{
“access_token”:“ACCESS_TOKEN”,
“expires_in”:7200,
“refresh_token”:“REFRESH_TOKEN”,
“openid”:“OPENID”,
“scope”:“SCOPE”,
“unionid”: “o6_bmasdasdsad6_2sgVt7hMZOPfL”
}
参数说明
参数 说明
access_token 接口调用凭证
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔
unionid 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。
错误返回样例:
{“errcode”:40029,“errmsg”:“invalid code”}
刷新access_token有效期
access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:
- 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;
- 若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。
refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。
请求方法
获取第一步的code后,请求以下链接进行refresh_token:
https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
参数说明
参数 是否必须 说明
appid 是 应用唯一标识
grant_type 是 填refresh_token
refresh_token 是 填写通过access_token获取到的refresh_token参数
返回说明
正确的返回:
{
“access_token”:“ACCESS_TOKEN”,
“expires_in”:7200,
“refresh_token”:“REFRESH_TOKEN”,
“openid”:“OPENID”,
“scope”:“SCOPE”
}
参数说明
参数 说明
access_token 接口调用凭证
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔
错误返回样例:
{“errcode”:40030,“errmsg”:“invalid refresh_token”}
注意:
1、Appsecret 是应用接口使用**,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);
2、access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;
3、refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上。
建议将secret、用户数据(如access_token)放在App云端服务器,由云端中转接口调用请求。
.第三步:通过access_token调用接口
获取access_token后,进行接口调用,有以下前提:
- access_token有效且未超时;
- 微信用户已授权给第三方应用帐号相应接口作用域(scope)。
对于接口作用域(scope),能调用的接口有以下:
授权作用域(scope) 接口 接口说明
snsapi_base /sns/oauth2/access_token 通过code换取access_token、refresh_token和已授权scope
snsapi_base /sns/oauth2/refresh_token 刷新或续期access_token使用
snsapi_base /sns/auth 检查access_token有效性
snsapi_userinfo /sns/userinfo 获取用户个人信息
第四步:授权后接口调用(UnionID)
3.4.1.通过code获取access_token
接口说明
通过code获取access_token的接口。
请求说明
http请求方式: GET
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明
参数 是否必须 说明
appid 是 应用唯一标识,在微信开放平台提交应用审核通过后获得
secret 是 应用**AppSecret,在微信开放平台提交应用审核通过后获得
code 是 填写第一步获取的code参数
grant_type 是 填authorization_code
返回说明
正确的返回:
{
“access_token”:“ACCESS_TOKEN”,
“expires_in”:7200,
“refresh_token”:“REFRESH_TOKEN”,“openid”:“OPENID”,
“scope”:“SCOPE”
}
参数 说明
access_token 接口调用凭证
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔
错误返回样例:
{
“errcode”:40029,“errmsg”:“invalid code”
以下是实现代码:
配置hosts文件:
127.0.0.1 bugtracker.itsource.cn
192.168.1.103 bugtracker.itsource.cn
位置:C:\Windows\System32\drivers\etc
1.导入maven包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
2.工具类的封装
public class HttpClientUtil {
// http://bugtracker.itsource.cn/wechat/callback?code=222&state=99
// http://bugtracker.itsource.cn/wechat/callback code=222&state=99
public static String doGet(String uri){
//1:创建一个HttpClient的实例
CloseableHttpClient httpclient = HttpClients.createDefault();
//2:创建一个get请求实例
HttpGet httpGet = new HttpGet(uri);
//请求的响应:
CloseableHttpResponse response1=null;
try {
//3:使用HttpClient的实例执行get请求
response1= httpclient.execute(httpGet);
//http请求的状态:404 500 200
System.out.println(response1.getStatusLine());
int statusCode = response1.getStatusLine().getStatusCode();
if(statusCode==200){
//请求成功:
HttpEntity entity1 = response1.getEntity();
String result = EntityUtils.toString(entity1, "utf-8");
System.out.println(result);
return result;
}else{
//请求失败:自己做自己的业务逻辑
}
}catch (Exception ex){
ex.printStackTrace();
}
return null;
}
*3.常量封装*
public class WxConstants {
public final static String APPID = "wxd853562a0548a7d0";
//用户授权后微信的回调域名
public final static String CALLBACK="http://bugtracker.itsource.cn";
public final static String SCOPE = "snsapi_login";
public final static String APPSECRET = "4a5d5615f93f24bdba2ba8534642dbb6";
//微信上获取code的地址
public final static String CODEURL = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
//微信上获取at的地址
public final static String ACCESSTOKEURL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
//微信上获取用户信息的地址
public final static String USERINFOURL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
}
4.核心代码
@Controller
@RequestMapping("/wechat")
public class WeChatController {
@RequestMapping("/login")
public String index(){
return "wxlogin";
}
@RequestMapping("/callback")
public String callback(String code, String state, Model model, HttpServletRequest req){
String atUrl = WeChatConstants.ACCESS_TOKEN.replace("APPID",WeChatConstants.APPID)
.replace("SECRET",WeChatConstants.SECRET)
.replace("CODE",code);
String atJsonStr = HttpClientUtil.doGet(atUrl);
System.out.println("atJsonStr:"+atJsonStr);
JSONObject jsonObject = (JSONObject)JSON.parse(atJsonStr);
String access_token = String.valueOf(jsonObject.get("access_token"));
String open_id = String.valueOf(jsonObject.get("openid"));
System.out.println("access_token:"+access_token);
System.out.println("open_id:"+open_id);
String userInfoUrl = WeChatConstants.USER_INFO.replace("ACCESS_TOKEN", access_token).replace("OPENID", open_id);
String userInfo = HttpClientUtil.doGet(userInfoUrl);
JSONObject userJson = (JSONObject)JSON.parse(userInfo);
System.out.println(userJson);
//完成绑定操作
model.addAttribute("userInfo", userInfo);
return "main";
}
}
5.创建login页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="/wechat/login1">微信登录</a>
</body>
</html>
6.拉起微信的登录二维码页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>微信登录</title>
<link rel="icon" href="/static/images/wx.ico">
</head>
<body>
<script type="text/javascript" src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
<div style="Text-align:center;width:100%;">
<div id="login_container"></div>
</div>
<script type="text/javascript">
var obj = new WxLogin({
self_redirect:false,
id:"login_container",
appid: "wxd853562a0548a7d0",
scope: "snsapi_login",
redirect_uri: "http://bugtracker.itsource.cn/wechat/callback",
state: "xxx",
style: "black",
href: ""
});
</script>
</body>
</html>
下一篇: php cookie解决方法