欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第三方登录之微信登录流程和代码

程序员文章站 2022-06-12 20:23:49
...

微信登录:
在第三方注册一个账号;访问地址,获取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刷新结果有两种:

  1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;
  2. 若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后,进行接口调用,有以下前提:

  1. access_token有效且未超时;
  2. 微信用户已授权给第三方应用帐号相应接口作用域(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>