第三方网站对接微信扫码登录(springboot+vue)

前言

现在越来越多的互联网应用需要对接第三方用户登录(比如:微信、QQ、新浪微博等),今天我就记录一下在springboot+vue前后端分离项目中对接微信扫描二维码登录的步骤及相关代码。
项目中使用的架构:后端spingboot + mybatis + shrio、前端vue + element-ui。
参考文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

第一步 新建网站应用

微信开放平台认证的过程相对慢些,提交完公司相关资料审核通过需要2~3天左右。开放平台账号准备好后我们开始新建网站应用(个人是没有资格认证开放平台的,请注意!!! )。
在这里插入图片描述
在这里插入图片描述
提交审核后就等着吧,网站应用的审核时间是1~2天,审核通过后我们就可以拿到AppID和AppSecret了。
在这里插入图片描述

第二步 编码及测试

前端引用了vue-wxlogin插件,需要在前端项目中执行以下命令:

npm install vue-wxlogin --save-dev

在login.vue中导入改插件:

import wxlogin from 'vue-wxlogin'

在需要显示二维码的地方贴入以下代码:

 <wxlogin :theme="'black'"
                   :appid="appid"
                   :scope="'snsapi_login'"
                   :redirect_uri="redirect_uri"></wxlogin>

在login.vue的creator钩子函数中贴入下面代码:

getwxcode () {
      if (this.$route.query.code) {
        this.code = this.$route.query.code
        let params = {}
        params.appid = this.appid
        params.secret = this.secret
        params.code = this.code
        params.grant_type = 'authorization_code'
        getAccessToken(params).then((res) => {
          if (res.code === 0) {
            this.$cookie.set('token', res.token)
            this.$router.replace({ name: 'home' })
          } else if (res.code === 500) {
            this.dialogVisible4 = true
            this.openId = res.openId
          } else {
            this.$message({
              message: res.msg,
              type: 'error'
            })
          }
        })
      }
    },

用户扫描二维码确认登录之后还回调到登录页面,执行获取getAccessToken请求,后端根据获取到的用户openid到用户中心查询用户,能查询用户的话登录成功,查不到用户会提示绑定账号。
后端代码:

@RequestMapping("/getAccessToken")
    public void getAccessToken(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("application/json; charset=utf-8");
        PrintWriter out = null;
        JSONObject tempJson = new JSONObject();

        String code = request.getParameter("code");
        String grantType = "authorization_code";
        JSONObject result = JSONObject.parseObject(HttpsUtils.sendGetRequest(accessTokenUrl+"?&appid=" + appId + "&secret=" + secret + "&code=" + code + "&grant_type=" + grantType, null));
        openid = result.get("openid").toString();
        try {
            out = response.getWriter();

            //查询用户信息
            UserEntity userEntity = userService.queryByPcOpenId(openid);
            if(org.springframework.util.StringUtils.isEmpty(userEntity)){
                tempJson.put("msg", "根据OPENID查询不到用户!");
                tempJson.put("openId", openid);
                tempJson.put("code", 500);
                out.append(tempJson.toJSONString());
            } else {
                R r = sysTokenService.createToken(userEntity.getId(),"sys");
                tempJson.put("openId", openid);
                tempJson.put("token", r.get("token"));
                tempJson.put("code", 0);
                out.append(tempJson.toJSONString());
            }
        } catch (Exception e) {
            userService.updateOpenIdIsNull(openid);
            e.printStackTrace();
        }
    }

HttpsUtils代码:

package cn.demo.common.utils;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
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 javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
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.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
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;

public class HttpsUtils {
    private static Logger logger = LoggerFactory.getLogger(HttpsUtils.class);
    static CloseableHttpClient httpClient;
    static CloseableHttpResponse httpResponse;

    public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                // 信任所有
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();

    }

    /**
     * 发送HTTP_GET请求
     * @see 该方法会自动关闭连接,释放资源
     * @param requestURL    请求地址(含参数)
     * @param decodeCharset 解码字符集,解析响应数据时用之,其为null时默认采用UTF-8解码
     * @return 远程主机响应正文
     */
    public static String sendGetRequest(String reqURL, String decodeCharset){
        long responseLength = 0;       //响应长度
        String responseContent = null; //响应内容
        HttpClient httpClient = new DefaultHttpClient(); //创建默认的httpClient实例
        HttpGet httpGet = new HttpGet(reqURL);           //创建org.apache.http.client.methods.HttpGet
        try{
            HttpResponse response = httpClient.execute(httpGet); //执行GET请求
            HttpEntity entity = response.getEntity();            //获取响应实体
            if(null != entity){
                responseLength = entity.getContentLength();
                responseContent = EntityUtils.toString(entity, decodeCharset==null ? "UTF-8" : decodeCharset);
                EntityUtils.consume(entity); //Consume response content
            }
            System.out.println("请求地址: " + httpGet.getURI());
            System.out.println("响应状态: " + response.getStatusLine());
            System.out.println("响应长度: " + responseLength);
            System.out.println("响应内容: " + responseContent);
        }catch(ClientProtocolException e){
            logger.debug("该异常通常是协议错误导致,比如构造HttpGet对象时传入的协议不对(将'http'写成'htp')或者服务器端返回的内容不符合HTTP协议要求等,堆栈信息如下", e);
        }catch(ParseException e){
            logger.debug(e.getMessage(), e);
        }catch(IOException e){
            logger.debug("该异常通常是网络原因引起的,如HTTP服务器未启动等,堆栈信息如下", e);
        }finally{
            httpClient.getConnectionManager().shutdown(); //关闭连接,释放资源
        }
        return responseContent;
    }

    /**
     * 发送https请求
     *
     * @param
     * @throws Exception
     */
    public static String sendByHttp(Map<String, Object> params, String url) {
        try {
            HttpPost httpPost = new HttpPost(url);
            List<NameValuePair> listNVP = new ArrayList<NameValuePair>();
            if (params != null) {
                for (String key : params.keySet()) {
                    listNVP.add(new BasicNameValuePair(key, params.get(key).toString()));
                }
            }
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(listNVP, "UTF-8");
            logger.info("创建请求httpPost-URL={},params={}", url, listNVP);
            httpPost.setEntity(entity);
            httpClient = HttpsUtils.createSSLClientDefault();
            httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                String jsObject = EntityUtils.toString(httpEntity, "UTF-8");
                return jsObject;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                httpResponse.close();
                httpClient.close();
                logger.info("请求流关闭完成");
            } catch (IOException e) {
                logger.info("请求流关闭出错");
                e.printStackTrace();
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值