微信小程序登入 uniapp+SpringBoot

微信小程序登入

前端登入流程

1-获取code
2-获取昵称 头像
3-把code 昵称 头像 封装成data对象
4-调用登入接口 传入data对象
5-把请求结果token缓存到本地

uniapp代码

<template>
	<view>
		<button @click="login">登入</button>
	</view>
</template>

<script>
	export default {
		methods: {

			async login() {
				Promise.all([this.getCode(), this.getUserInfo()]).then(res => {
					// 3-把code 昵称 头像 封装成data对象
					let data = {
						code: res[0].code,
						nickName: res[1].userInfo.nickName,
						avatarUrl: res[1].userInfo.avatarUrl
					}
					console.log('用户的登入信息', data);
					
					// 4-调用登入接口 传入data对象
					uni.request({
						url: "http://192.168.2.127:6450/my/login",
						method: 'POST',
						data: data,
						success: (res) => {
							
							// 5-把请求结果token缓存到本地
							console.log("登入结果", res);
							uni.setStorageSync('token', res.data.token);
						}
					});


				})
			},

			// 1-获取code
			getCode() {
				return new Promise((resolve, reject) => {
					wx.login({
						timeout: 5000,
						success: (res) => {
							resolve(res)
						},
						fail: (err) => {
							reject(err)
						}
					})
				});
			},

			// 2-获取头像和昵称
			getUserInfo() {
				return new Promise((resolve, reject) => {
					wx.getUserProfile({
						desc: "获取用户信息",
						success: (res) => {
							resolve(res)
						},
						fail: (err) => {
							reject(err)
						}
					})
				});
			},


		}
	}
</script>

服务器

服务器登入流程

1-整理数据,需要如下

// 请求地址 固定值
String url="https://api.weixin.qq.com/sns/jscode2session";
// AppID(小程序ID)
String appid="wx8e25486c2bdafe11";
// AppSecret(小程序密钥)
String secret="cce5a87eeb5f0ff39f75db1be2f05088";
// 登录时获取的 code
String js_code=user.getCode();
// 授权类型,此处只需填写 authorization_code 固定值
String grant_type="authorization_code";

2-拼接地址

 String path=url+"?appid="+appid+"&secret="+secret+"&js_code="+js_code+"&grant_type="+grant_type;

3-使用HttpClientUtil工具类发送get请求拼接后的地址得到json结果
4-使用fastjson解析json结果得到openid
5-根据openid查询数据库判断该用户是否存在
-存在,更新该用户的数据
-不存在,添加该用户
6-根据openid生成token返回前端

SpringBoot代码

登入接口

package com.example.server.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.server.constant.SystemConstant;
import com.example.server.pojo.WxUser;
import com.example.server.utils.HttpClientUtil;
import com.example.server.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author 刘帅乐
 * @Date 2022/6/29 11:44
 * @Version 1.0
 */

@RestController
@RequestMapping("/my")
public class MyController {

    @Autowired
    HttpClientUtil http;

    @PostMapping("/login")
    public Map login(@RequestBody WxUser user) {
        System.out.println("用户信息:"+user);


        /* 1-整理数据,需要如下 */
        // 请求地址
        String url="https://api.weixin.qq.com/sns/jscode2session";
        //小程序 appId
        String appid="wx8e25486c2bdafe11";
        //小程序 appSecret
        String secret="cce5a87eeb5f0ff39f75db1be2f05088";
        //登录时获取的 code
        String js_code=user.getCode();
        // 授权类型,此处只需填写 authorization_code
        String grant_type="authorization_code";


        /* 2-拼接地址 */
        String path=url+"?appid="+appid+"&secret="+secret+"&js_code="+js_code+"&grant_type="+grant_type;
        System.out.println("拼接后的请求路径:"+path);


        /* 3-使用HttpClientUtil工具类发送get请求拼接后的地址得到json结果 */
        String res=http.sendHttpGet(path);
        System.out.println("请求结果:"+res);


        /* 4-使用fastjson解析json结果得到openid */
        JSONObject jsonObject= JSON.parseObject(res);
        String openid = jsonObject.get("openid").toString();
        System.out.println("openid是:"+openid);


        /* 5-根据openid查询数据库判断该用户是否存在 */
        // 主要是演示登入的代码,为了不混淆视听操作数据库的代码就不演示了。这一步不写也能跑通


        /* 6-根据openid生成token返回前端 */
        String token = JwtUtils.createJWT(openid, user.getNickName(), SystemConstant.JWT_TTL);
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("token",token);
        System.out.println("返回前端token:"+token);
        return resultMap;
    }
}

上面代码还需要下面几个步骤才能运行

1-引入依赖
		<!-- JWT -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>


        <!-- 添加Httpclient支持 -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
		
			
        <!--json-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.40</version>
        </dependency>

2-创建SystemConstant类

在如下位置创建

微信小程序登入 uniapp+SpringBoot_第1张图片

package com.example.server.constant;

/**
 * 系统级静态变量
 * @Author 刘帅乐
 * @Date 2022/6/29 14:53
 * @Version 1.0
 */
public class SystemConstant {

    //Token不存在
    public static final int JWT_ERRCODE_NULL = 4000;
    //Token过期
    public static final int JWT_ERRCODE_EXPIRE = 4001;
    //验证不通过
    public static final int JWT_ERRCODE_FAIL = 4002;

    //密匙
    public static final String JWT_SECERT = "8677df7fc3a34e26a61c034d5ec8245d";
    public static final long JWT_TTL = 24 * 60 * 60 * 1000;
}

3-创建HttpClientUtil工具类
package com.example.server.utils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
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.DefaultHostnameVerifier;
import org.apache.http.conn.util.PublicSuffixMatcher;
import org.apache.http.conn.util.PublicSuffixMatcherLoader;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author 刘帅乐
 * @Date 2022/6/29 14:32
 * @Version 1.0
 */

@Component
public class HttpClientUtil {


    /**
     * 默认参数设置
     * setConnectTimeout:设置连接超时时间,单位毫秒。
     * setConnectionRequestTimeout:设置从connect Manager获取Connection 超时时间,单位毫秒。
     * setSocketTimeout:请求获取数据的超时时间,单位毫秒。访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。 暂时定义15分钟
     */
    private RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(600000).setConnectTimeout(600000).setConnectionRequestTimeout(600000).build();

    /**
     * 静态内部类---作用:单例产生类的实例
     * @author Administrator
     *
     */
    private static class LazyHolder {
        private static final HttpClientUtil INSTANCE = new HttpClientUtil();

    }
    private HttpClientUtil(){}
    public static HttpClientUtil getInstance(){
        return LazyHolder.INSTANCE;
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     */
    public String sendHttpPost(String httpUrl) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param params 参数(格式:key1=value1&key2=value2)
     */
    public String sendHttpPost(String httpUrl, String params) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param maps 参数
     */
    public String sendHttpPost(String httpUrl, Map<String, String> maps) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        // 创建参数队列
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (String key : maps.keySet()) {
            nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送Post请求
     * @param httpPost
     * @return
     */
    private String sendHttpPost(HttpPost httpPost) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例
            httpClient = HttpClients.createDefault();
            httpPost.setConfig(requestConfig);
            // 执行请求
            long execStart = System.currentTimeMillis();
            response = httpClient.execute(httpPost);
            long execEnd = System.currentTimeMillis();
            System.out.println("=================执行post请求耗时:"+(execEnd-execStart)+"ms");
            long getStart = System.currentTimeMillis();
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
            long getEnd = System.currentTimeMillis();
            System.out.println("=================获取响应结果耗时:"+(getEnd-getStart)+"ms");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    /**
     * 发送 get请求
     * @param httpUrl
     */
    public String sendHttpGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
        return sendHttpGet(httpGet);
    }

    /**
     * 发送 get请求Https
     * @param httpUrl
     */
    public String sendHttpsGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
        return sendHttpsGet(httpGet);
    }

    /**
     * 发送Get请求
     * @param httpGet
     * @return
     */
    private String sendHttpGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.


            httpClient = HttpClients.createDefault();

            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    /**
     * 发送Get请求Https
     * @param httpGet
     * @return
     */
    private String sendHttpsGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpGet.getURI().toString()));
            DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
            httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    /**
     * 发送xml数据
     * @param url
     * @param xmlData
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static HttpResponse sendXMLDataByPost(String url, String xmlData)
            throws ClientProtocolException, IOException {
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httppost = new HttpPost(url);
        StringEntity entity = new StringEntity(xmlData);
        httppost.setEntity(entity);
        httppost.setHeader("Content-Type", "text/xml;charset=UTF-8");
        HttpResponse response = httpClient.execute(httppost);
        return response;
    }

    /**
     * 获得响应HTTP实体内容
     *
     * @param response
     * @return
     * @throws IOException
     * @throws UnsupportedEncodingException
     */
    public static String getHttpEntityContent(HttpResponse response) throws IOException, UnsupportedEncodingException {
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream is = entity.getContent();
            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String line = br.readLine();
            StringBuilder sb = new StringBuilder();
            while (line != null) {
                sb.append(line + "\n");
                line = br.readLine();
            }
            return sb.toString();
        }
        return "";
    }

}

4-创建JwtUtils工具类
package com.example.server.utils;



import com.example.server.constant.SystemConstant;
import com.example.server.pojo.CheckResult;
import io.jsonwebtoken.*;
import org.bouncycastle.util.encoders.Base64;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;


/**
 *
 * @Author 刘帅乐
 * @Date 2022/6/29 14:45
 * @Version 1.0
 */

public class JwtUtils {

    /**
     * 签发JWT
     * @param id
     * @param subject 可以是JSON数据 尽可能少
     * @param ttlMillis
     * @return
     */
    public static String createJWT(String id, String subject, long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setId(id)
                .setSubject(subject)   // 主题
                .setIssuer("hrkj")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey); // 签名算法以及密匙
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date expDate = new Date(expMillis);
            builder.setExpiration(expDate); // 过期时间
        }
        return builder.compact();
    }

    /**
     * 验证JWT
     * @param jwtStr
     * @return
     */
    public static CheckResult validateJWT(String jwtStr) {
        CheckResult checkResult = new CheckResult();
        Claims claims = null;
        try {
            claims = parseJWT(jwtStr);
            checkResult.setSuccess(true);
            checkResult.setClaims(claims);
        } catch (ExpiredJwtException e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_EXPIRE);
            checkResult.setSuccess(false);
        } catch (SignatureException e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        } catch (Exception e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        }
        return checkResult;
    }

    /**
     * 生成加密Key
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode(SystemConstant.JWT_SECERT);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }


    /**
     * 解析JWT字符串
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }

}

最后可以会报错

微信小程序登入 uniapp+SpringBoot_第2张图片

原因:新版的JDK不会自带javax.xml.bind相关的包了,导致执行时无法找到具体的类文件。
方案1:
降低jdk版本为1.8
方案2:
手动引入缺少的依赖文件

        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>

你可能感兴趣的:(微信小程序,spring,boot,小程序)