Spring Boot實現(xiàn)微信小程序登錄
使用Spring Boot完成微信小程序登錄
由于微信最近的版本更新,wx.getUserInfo()的這個接口即將失效,將用wx.getUserProfile()替換,所以近期我也對自己的登錄進行更新,并且為了鞏固學(xué)習(xí)到的知識,我自己做了一個小demo,在此分享給大家,希望能對大家有所幫助。廢話不多說,直接上代碼。
前端
.wxml
<button class="r" bindtap="bindGetUserInfo">同意</button>
JS部分
bindGetUserInfo(e) { let that = this let token = wx.getStorageSync('token'); //token其實就是后臺調(diào)用微信登錄接口返回的openid,每個用戶在同一個小程序內(nèi)是唯一的。 wx.showLoading({ title: '加載中', //提示框,加載中的樣式 }) if (token) { //如果已經(jīng)有token,說明用戶已經(jīng)登錄,跳轉(zhuǎn)到指定頁面 wx.switchTab({ url: '' }) } else { //用戶還未登錄,申請用戶授權(quán) wx.getUserProfile({ desc: '用于完善會員資料', // 聲明獲取用戶個人信息后的用途,后續(xù)會展示在彈窗中,請謹慎填寫 success: (res) => { that.setData({ userInfo: res.userInfo, //保存用戶信息 }) if (res.errMsg == "getUserProfile:ok") { let code = null wx.login({ success: function (e) { code = e.code let params = {}; params.code = code; //用戶code 注:用戶的code每次登錄都是隨機的,所以不需要進行存儲 params.avatarUrl = res.userInfo.avatarUrl; //用戶頭像 params.nickName = res.userInfo.nickName; //用戶微信名 params.gender = res.userInfo.gender; //用戶性別 0為未知,1為男,2為女 //還有有用戶微信設(shè)置的地址信息,個人認為沒啥用,所以沒處理 wx.request({ url: '', //后臺接口 data: params, method: 'POST', header: { 'Content-Type': 'application/json', 'X-Nideshop-Token': wx.getStorageSync('token') }, success: function (res) { //URL為你后臺的接口 console.log(res) if (res.data.code === 200) { //存儲用戶信息 wx.setStorageSync('userInfo', res.data.userInfo); wx.setStorageSync('token', res.data.userInfo.openId); wx.switchTab({ url: '' //跳轉(zhuǎn)到指定頁面 }) wx.hideLoading() //關(guān)閉提示框 } else { //輸出錯誤信息 } } }) } }) } else { //用戶按了拒絕按鈕 wx.showModal({ title: '警告通知', content: '您點擊了拒絕授權(quán),將無法正常顯示個人信息,點擊確定重新獲取授權(quán)。', success: function (res) { //用戶拒絕登錄后的處理 } }); } } }) } },
前臺的部分都在這了,詳細的解釋都寫在注釋里了,如果多處使用登錄、或者校驗用戶是否登錄,建議進行封裝,方便調(diào)用。
后臺
后臺部分我使用的是springboot框架,為了方便新手學(xué)習(xí),我會將整個模塊貼在后面,包括jar包。
首先給大家看一下項目目錄結(jié)構(gòu)
POM.XML
jar包的內(nèi)容并不復(fù)雜,我相信各位應(yīng)該都沒啥問題哈哈哈哈哈
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> <!--數(shù)據(jù)庫--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.4.4</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <!--SpringBoot啟動器--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency>
配置類 application.yml
配置類的內(nèi)容也不復(fù)雜,在此就不作解釋啦
mybatis: type-aliases-package: com.cxb.pojo config-location: classpath:mybatis/mybatis-config.xml mapper-locations: classpath:mybatis/mapper/*.xml spring: application: name: item #數(shù)據(jù)庫部分 datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql:///item?useUnicode=treu&charactEncoding=utf-8 username: root password: 123456 wxMini: appId: #小程序的appid,在哪獲取如果不知道的話可以百度喲 secret: #小程序密匙
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="cacheEnabled" value="true"/> <!--開啟二級緩存--> </settings> </configuration>
工具類 WeChatUtil
這個工具類是我網(wǎng)上找的一個比較簡單的工具類,因為微信登錄接口返回的參數(shù)是加密的,所以需要解密
package com.cxb.utils; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; /** * 微信小程序工具類 */ @Slf4j public class WeChatUtil { public static String httpRequest(String requestUrl, String requestMethod, String output) { try { URL url = new URL(requestUrl); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setUseCaches(false); connection.setRequestMethod(requestMethod); if (null != output) { OutputStream outputStream = connection.getOutputStream(); outputStream.write(output.getBytes(StandardCharsets.UTF_8)); outputStream.close(); } // 從輸入流讀取返回內(nèi)容 InputStream inputStream = connection.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str; StringBuilder buffer = new StringBuilder(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); inputStream.close(); connection.disconnect(); return buffer.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } /** * 向指定 URL 發(fā)送POST方法的請求 * * @param url 發(fā)送請求的 URL * @param json 請求參數(shù),請求參數(shù)應(yīng)該是 json 的形式。 * @return 所代表遠程資源的響應(yīng)結(jié)果 */ public static String httpPost(String url, JSONObject json) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打開和URL之間的連接 URLConnection conn = realUrl.openConnection(); // 設(shè)置通用的請求屬性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 發(fā)送POST請求必須設(shè)置如下兩行 conn.setDoOutput(true); conn.setDoInput(true); // 獲取URLConnection對象對應(yīng)的輸出流 out = new PrintWriter(conn.getOutputStream()); // 發(fā)送請求參數(shù) out.print(json); // flush輸出流的緩沖 out.flush(); // 定義BufferedReader輸入流來讀取URL的響應(yīng) in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result=result.concat(line); } } catch (Exception e) { System.out.println("發(fā)送 POST 請求出現(xiàn)異常!" + e); e.printStackTrace(); } //使用finally塊來關(guān)閉輸出流、輸入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } }
接下來就是項目的主題代碼了,因為只是做一個簡單的demo,所以內(nèi)容并不復(fù)雜,但是不管是學(xué)習(xí)還是普通的小項目都是沒有問題的,可以放心使用
Dao層 UserDao
package com.cxb.dao; import com.cxb.pojo.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @Mapper @Repository public interface UserDao { User queryById(String openId); void insertUser(User user); void updateUser(User user); }
service層 UserService
package com.cxb.service; import com.cxb.dao.UserDao; import com.cxb.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserService implements UserDao { @Autowired private UserDao userDao; @Override public User queryById(String openId) { return userDao.queryById(openId); } @Override public void insertUser(User user) { userDao.insertUser(user); } @Override public void updateUser(User user) { userDao.updateUser(user); } }
實體類 User
package com.cxb.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.io.Serializable; import java.util.Date; @Data @NoArgsConstructor @Accessors(chain = true) public class User implements Serializable { private Long id; //id private String code; //只是為了能接收參數(shù),不需要存入數(shù)據(jù)庫 private String openId; //微信登錄接口返回的參數(shù)之一,就是token private String nickName; //微信名 private String avatarUrl; //頭像 private String gender; //性別 0 未知 1 男 2 女 private Date firstLoginTime; //第一次登錄時間 private Date lastLoginTime; //最后一次登錄時間 }
SQL部分 UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapepr 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cxb.dao.UserDao"> <select id="queryById" resultType="User"> select * from user where open_id = #{openId} </select> <insert id="insertUser" parameterType="User"> insert into user ( open_id, nick_name, avatar_url, gender, first_login_time, last_login_time ) values( #{openId}, #{nickName}, #{avatarUrl}, #{gender}, #{firstLoginTime}, #{lastLoginTime} ) </insert> <update id="updateUser" parameterType="User"> update user <set> <if test="nickName != null">`nick_name` = #{nickName},</if> <if test="avatarUrl != null">`avatar_url` = #{avatarUrl},</if> <if test="gender != null">`gender` = #{gender},</if> <if test="lastLoginTime != null">`last_login_time` = #{lastLoginTime}</if> </set> where id = #{id} </update> </mapper>
控制器 UserController
package com.cxb.controller; import com.alibaba.fastjson.JSONObject; import com.cxb.pojo.User; import com.cxb.service.UserService; import com.cxb.utils.WeChatUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.Date; @Controller @RequestMapping(value = "/user") public class UserController { @Value("${wxMini.appId}") public String appId; @Value("${wxMini.secret}") public String secret; @Autowired private UserService userService; @RequestMapping(value = "/login",method = RequestMethod.POST) @ResponseBody public JSONObject login(@RequestBody User user){ String code = user.getCode(); JSONObject object=new JSONObject(); if(code == "" || "".equals(code)){ object.put("code",300); object.put("msg","code不能為空!"); return object; } else { //微信接口服務(wù),通過調(diào)用微信接口服務(wù)中jscode2session接口獲取到openid和session_key String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code"; String str = WeChatUtil.httpRequest(url, "GET", null); //調(diào)用工具類解密 JSONObject jsonObject=JSONObject.parseObject(str); String openid = (String) jsonObject.get("openid"); if(openid != null && !"".equals(openid)){ //登錄成功 User userVo=new User(); userVo.setNickName(user.getNickName()); userVo.setAvatarUrl(user.getAvatarUrl()); userVo.setOpenId(openid); userVo.setGender(user.getGender()); userVo.setFirstLoginTime(new Date(System.currentTimeMillis())); userVo.setLastLoginTime(new Date(System.currentTimeMillis())); User us = userService.queryById(openid); if(us != null) { //不是首次登錄,更新用戶信息 userVo.setId(us.getId()); userService.updateUser(userVo); } else { //首次登錄,存儲用戶信息 userService.insertUser(userVo); } object.put("code",200); object.put("msg","登錄成功!"); object.put("userInfo",userVo); return object; }else { object.put("code",400); object.put("msg","未知錯誤,請重試!"); return object; } } } }
啟動類 item
package com.cxb; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; @SpringBootApplication public class item { //讀取配置文件信息 @Bean public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() { PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer(); c.setIgnoreUnresolvablePlaceholders(true); return c; } public static void main(String[] args) { SpringApplication.run(item.class,args); } }
數(shù)據(jù)庫的部分應(yīng)該就不用分享了吧,相信大家根據(jù)實體類能自己建出來,好啦,至此微信小程序的登錄功能就完成啦,希望能對大家有所幫助。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MyBatisPlus代碼生成器的原理及實現(xiàn)詳解
這篇文章主要為大家詳細介紹了MyBatisPlus中代碼生成器的原理及實現(xiàn),文中的示例代碼講解詳細,對我們學(xué)習(xí)MyBatisPlus有一定幫助,需要的可以參考一下2022-08-08java swing 創(chuàng)建一個簡單的QQ界面教程
這篇文章主要介紹了java swing 創(chuàng)建一個簡單的QQ界面教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09MyBatis-Plus攔截器實現(xiàn)數(shù)據(jù)權(quán)限控制的方法
MyBatis-Plus是一款基于MyBatis的增強工具,它提供了一些便捷的功能和增強的查詢能力,數(shù)據(jù)權(quán)限控制是在系統(tǒng)中對用戶訪問數(shù)據(jù)進行限制的一種機制,這篇文章主要給大家介紹了關(guān)于MyBatis-Plus攔截器實現(xiàn)數(shù)據(jù)權(quán)限控制的相關(guān)資料,需要的朋友可以參考下2024-01-01