日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

微信小程序结合Java后端实现登录注册

發(fā)布時(shí)間:2023/12/10 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 微信小程序结合Java后端实现登录注册 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

微信小程序登錄

    • 微信用戶,授權(quán)信息,相關(guān)實(shí)體類
      • 微信用戶表
      • 實(shí)體類
      • 獲取微信的token
      • 常量抽取
    • httpClient工具,用于發(fā)送請(qǐng)求獲取token
      • nbplus pom
      • 工具類
    • 請(qǐng)求微信后臺(tái),獲取openid,返回的是json
    • 登錄或者注冊完整業(yè)務(wù)實(shí)現(xiàn),登錄成功返回jwt簽名
      • cotroller實(shí)現(xiàn)
      • 業(yè)務(wù)實(shí)現(xiàn)
    • 設(shè)置攔截器對(duì)要訪問的方法攔截,并判斷jwt token
      • 增加注解,靈活判斷哪些controlelr方法需要配token驗(yàn)證
      • 攔截器

登錄,微信api
后臺(tái)獲取微信token,包括openid在內(nèi)

登錄流程 1. 小程序發(fā)起wx.login請(qǐng)求獲取jscode 2. 獲取jscode,發(fā)送到自己的后端 3. 自己的后臺(tái)發(fā)請(qǐng)求帶上jscode, appid(當(dāng)前用戶的唯一標(biāo)識(shí)), secretkey到微信的后端獲取session_key, openid 4. 返回session_key或者openid到頁面 5. 頁面再發(fā)請(qǐng)求到后臺(tái)驗(yàn)證openid 是否存在, 存在即登錄。 不存在 保存openid到個(gè)人數(shù)據(jù)庫,即注冊。 6. 登錄成功后,返回jwt token簽名 7. 頁面通過微信app.js 的globalData保存openid,jwt token信息

微信用戶,授權(quán)信息,相關(guān)實(shí)體類

微信用戶表

create table forum_info.wei_xin_user (id int auto_increment primary key,user_name varchar(30) null,user_pwd varchar(30) null,# 這里的密碼沒用,登錄只是驗(yàn)證open_id, # 所以說小程序登錄是不需要密碼的額。它問你是否授權(quán)。# 然后收集你的其它個(gè)人信息。create_date date null,wx_open_id varchar(30) null );

實(shí)體類

package top.bitqian.entity;import java.util.Date; import java.io.Serializable;import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import lombok.Data; import lombok.EqualsAndHashCode;/*** <p>* 微信用戶注冊實(shí)體類~* </p>** @author echo lovely* @since 2020-12-04*/ @Data @EqualsAndHashCode(callSuper = false) public class WeiXinUser implements Serializable {private static final long serialVersionUID = 1L;@TableId(type = IdType.AUTO)private Integer id;private String userName;private String userPwd;private Date createDate;private String wxOpenId;}

獲取微信的token

文檔里面的字段搬過來。

package top.bitqian.entity;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;/*** <p>* 調(diào)用微信接口 返回授權(quán)信息~* </p>* @author echo lovely* @date 2020/12/4 21:56*/@Data @NoArgsConstructor @AllArgsConstructor public class Code2Session {//用戶唯一標(biāo)識(shí)private String openid;// 會(huì)話密鑰private String session_key;// 用戶在開放平臺(tái)的唯一標(biāo)識(shí)符private String unionid;// 錯(cuò)誤碼private Integer errcode;// 錯(cuò)誤信息private String errmsg;}

常量抽取

package top.bitqian.config;/*** @author echo lovely* @date 2020/12/4 22:03*/public class WeiXinPostParamConstant {/*** 小程序appid*/public static String APP_ID = "小程序開發(fā)者官網(wǎng)生成";/*** 小程序 appSecret*/public static String SECRET = "小程序開發(fā)者官網(wǎng)生成";/*** 登錄時(shí)獲取的 code*/public static String JS_CODE = "";/*** 授權(quán)類型,此處只需填寫 authorization_code* grant_type ctrl + shit + u*/public static String GRANT_TYPE = "";}

httpClient工具,用于發(fā)送請(qǐng)求獲取token

nbplus pom

這里是boot,省略了version

<!-- http工具類 --><!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><!--<version>4.5.6</version>--></dependency><!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><!--<version>4.4.10</version>--></dependency>

工具類

package top.bitqian.config;import java.io.IOException; import java.io.InputStream; import java.net.SocketTimeoutException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Map;import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig.Builder; 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.client.methods.HttpRequestBase; import org.apache.http.client.utils.URIBuilder; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration;/*** HTTPClient 工具類.* @author echo lovely* @date 2020/12/4 21:44*/@Configuration @SuppressWarnings(value = "all") public class HttpClientUtil {private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);private static PoolingHttpClientConnectionManager connectionManager;private static String DEFAULT_STR = "";private static String UTF_8 = "UTF-8";private final static int CONNECT_TIMEOUT = 3000;// 連接超時(shí)毫秒 ps:表示建立連接的超時(shí)時(shí)間private final static int SOCKET_TIMEOUT = 10000;// 傳輸超時(shí)毫秒 ps:表示數(shù)據(jù)傳輸處理時(shí)間private final static int REQUESTCONNECT_TIMEOUT = 2000;// 從線程池獲取連接超時(shí)時(shí)間毫秒private final static int MAX_TOTAL = 50;// 線程池的最大連接數(shù)private final static int CONNECT_DEFAULT_ROUTE = 5;// 每個(gè)路由默認(rèn)基礎(chǔ)的連接數(shù)private static void init() {if (connectionManager == null) {connectionManager = new PoolingHttpClientConnectionManager();connectionManager.setMaxTotal(MAX_TOTAL);// 整個(gè)連接池最大連接數(shù)// 可用空閑連接過期時(shí)間,重用空閑連接時(shí)會(huì)先檢查是否空閑時(shí)間超過這個(gè)時(shí)間,如果超過,釋放socket重新建立//connectionManager.setValidateAfterInactivity(50000);connectionManager.setDefaultMaxPerRoute(CONNECT_DEFAULT_ROUTE);// 每路由最大連接數(shù),默認(rèn)值是2}}/*** 通過連接池獲取HttpClient** @return*/private static CloseableHttpClient getHttpClient() {init();Builder builder = RequestConfig.custom();RequestConfig config = builder.setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setConnectionRequestTimeout(REQUESTCONNECT_TIMEOUT).build();CloseableHttpClient client = HttpClients.custom().setMaxConnPerRoute(CONNECT_DEFAULT_ROUTE).disableConnectionState().setDefaultRequestConfig(config).setConnectionManager(connectionManager).build();return client;}/*** @param url* @return* @throws IOException*/public static String httpGetRequest(String url) throws Exception {HttpGet httpGet = new HttpGet(url);return getResult(httpGet);}public static String httpGetRequest(String url, Map<String, Object> params) throws Exception {URIBuilder ub = new URIBuilder();ub.setPath(url);ArrayList<NameValuePair> pairs = covertParams2NVPS(params);ub.setParameters(pairs);HttpGet httpGet = new HttpGet(ub.build());return getResult(httpGet);}public static String httpGetRequest(String url, Map<String, Object> headers, Map<String, Object> params) throws Exception {URIBuilder ub = new URIBuilder();ub.setPath(url);ArrayList<NameValuePair> pairs = covertParams2NVPS(params);ub.setParameters(pairs);HttpGet httpGet = new HttpGet(ub.build());for (Map.Entry<String, Object> param : headers.entrySet()) {httpGet.addHeader(param.getKey(), String.valueOf(param.getValue()));}return getResult(httpGet);}public static String httpPostRequest(String url) throws IOException {HttpPost httpPost = new HttpPost(url);return getResult(httpPost);}public static String httpPostRequest(String url, Map<String, Object> params) throws Exception {HttpPost httpPost = new HttpPost(url);ArrayList<NameValuePair> pairs = covertParams2NVPS(params);httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));return getResult(httpPost);}public static String httpPostRequest(String url, String jsonParams) throws Exception {HttpPost httpPost = new HttpPost(url);StringEntity se = new StringEntity(jsonParams, UTF_8);httpPost.setEntity(se);httpPost.setHeader("Content-Type", "application/json");return getResult(httpPost);}public static String httpPostXMLDataRequest(String url, String xmlData) throws Exception {HttpPost httpPost = new HttpPost(url);httpPost.addHeader("Content-Type", "text/xml");httpPost.setEntity(new StringEntity(xmlData, UTF_8));return getResult(httpPost);}/*** post** @param url (a=3&b=2 形式)* @param headers 請(qǐng)求頭* @param params 參數(shù)* @return* @throws IOException*/public static String httpPostRequest(String url, Map<String, Object> headers, Map<String, Object> params) throws Exception {HttpPost httpPost = new HttpPost(url);for (Map.Entry<String, Object> param : headers.entrySet()) {httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));}ArrayList<NameValuePair> pairs = covertParams2NVPS(params);httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));return getResult(httpPost);}private static ArrayList<NameValuePair> covertParams2NVPS(Map<String, Object> params) {ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();for (Map.Entry<String, Object> param : params.entrySet()) {pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue())));}return pairs;}/*** post** @param url (JSON 形式)* @param headers 請(qǐng)求頭* @param params 參數(shù)* @return* @throws IOException*/public static String httpPostRequest(String url, Map<String, Object> headers, String jsonParams) throws Exception {HttpPost httpPost = new HttpPost(url);for (Map.Entry<String, Object> param : headers.entrySet()) {httpPost.setHeader(param.getKey(), String.valueOf(param.getValue()));}StringEntity se = new StringEntity(jsonParams, UTF_8);httpPost.setEntity(se);return getResult(httpPost);}/*** 處理Http請(qǐng)求** @param request* @return string* @throws IOException*/private static String getResult(HttpRequestBase request) throws IOException {CloseableHttpClient httpClient = getHttpClient();CloseableHttpResponse response = null;InputStream in = null;try {response = httpClient.execute(request);HttpEntity entity = response.getEntity();in = response.getEntity().getContent();if (entity != null) {String result = EntityUtils.toString(entity, Charset.forName(UTF_8));response.close();return result;}} catch (ConnectTimeoutException e) {// 連接超時(shí)異常logger.error("connect timeout {}", e);} catch (SocketTimeoutException e) {// 讀取超時(shí)異常logger.error("read timeout {}", e);} catch (ClientProtocolException e) {// 該異常通常是協(xié)議錯(cuò)誤導(dǎo)致:比如構(gòu)造HttpGet對(duì)象時(shí)傳入?yún)f(xié)議不對(duì)(將'http'寫成'htp')or響應(yīng)內(nèi)容不符合logger.error("protocol exception {}", e);} catch (ParseException e) {// 解析異常logger.error("parse exception {}", e);} catch (IOException e) {// 該異常通常是網(wǎng)絡(luò)原因引起的,如HTTP服務(wù)器未啟動(dòng)等logger.error("network exception {}", e);} catch (Exception e) {logger.error("other exception {}", e);} finally {if (response != null) {try {response.close();} catch (IOException e) {e.printStackTrace();}}//in.close();作用就是將用完的連接釋放,下次請(qǐng)求可以復(fù)用//這里特別注意的是,如果不使用in.close();而僅僅使用response.close();結(jié)果就是連接會(huì)被關(guān)閉,并且不能被復(fù)用,這樣就失去了采用連接池的意義。if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}}return DEFAULT_STR;}public static void main(String[] args) {String str = null;try {str = HttpClientUtil.httpGetRequest("https://www.baidu.com");} catch (Exception e) {e.printStackTrace();}System.out.println(str);} }

請(qǐng)求微信后臺(tái),獲取openid,返回的是json

json轉(zhuǎn)實(shí)體類用

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
/*** 獲取openid session_key* @param jsCode 小程序請(qǐng)求到的jsCode* @return 授權(quán)信息~*/@Overridepublic Code2Session getWinXinJson(String jsCode) {// https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_codeStringBuilder url = new StringBuilder();url.append("https://api.weixin.qq.com/sns/jscode2session?appid=");url.append(WeiXinPostParamConstant.APP_ID);url.append("&secret=");url.append(WeiXinPostParamConstant.SECRET);url.append("&js_code=");url.append(jsCode);url.append("&grant_type=authorization_code");try {String weiXinJson = HttpClientUtil.httpGetRequest(url.toString());System.out.println(weiXinJson);return new ObjectMapper().readValue(weiXinJson, Code2Session.class);} catch (Exception e) {e.printStackTrace();}return null;}

登錄或者注冊完整業(yè)務(wù)實(shí)現(xiàn),登錄成功返回jwt簽名

我的java json web token簽名實(shí)現(xiàn),工具類

cotroller實(shí)現(xiàn)

package top.bitqian.controller;import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import top.bitqian.config.AuthTokenCheck; import top.bitqian.entity.Code2Session; import top.bitqian.entity.WeiXinUser; import top.bitqian.service.WeiXinUserService;import javax.servlet.http.HttpServletRequest; import java.util.Date;/*** 微信登錄 controller~* @author echo lovely* @date 2020/12/4 21:36*/@RestController @Slf4j public class WeiXinUserController {@Autowiredprivate WeiXinUserService weiXinUserService;// 調(diào)用微信的接口獲取 app_id@RequestMapping("/getCode/{jsCode}")public Code2Session getWinXinJson(@PathVariable("jsCode") String jsCode) {return weiXinUserService.getWinXinJson(jsCode);}// 用戶提交wx_id 過來注冊@RequestMapping("/wx_user/register")public boolean doRegister(WeiXinUser user) {// 賬號(hào)存在..WeiXinUser tmpUser = weiXinUserService.getWeiXinUserByOpenId(user.getWxOpenId());if (tmpUser != null) {return false;}// 不存在,即注冊user.setCreateDate(new Date(System.currentTimeMillis()));weiXinUserService.addWeiXinUser(user);return true;}@RequestMapping("/wx_user/login")public String doLogin(WeiXinUser weiXinUser) throws Exception {return weiXinUserService.doLogin(weiXinUser);}@AuthTokenCheck@RequestMapping("/wx_user/msg")public String testJwtToken(HttpServletRequest request) {Object userId = request.getAttribute("id");System.out.println("userId from page token~=======>" + userId);return "auth by token~" + userId;}}

業(yè)務(wù)實(shí)現(xiàn)

package top.bitqian.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import top.bitqian.config.HttpClientUtil; import top.bitqian.config.JwtUtil; import top.bitqian.config.WeiXinPostParamConstant; import top.bitqian.entity.Code2Session; import top.bitqian.entity.WeiXinUser; import top.bitqian.mapper.WeiXinUserMapper; import top.bitqian.service.WeiXinUserService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service;/*** <p>* 服務(wù)實(shí)現(xiàn)類* </p>** @author echo lovely* @since 2020-12-04*/ @Service public class WeiXinUserServiceImpl extends ServiceImpl<WeiXinUserMapper, WeiXinUser> implements WeiXinUserService {/*** 獲取openid session_key* @param jsCode 小程序請(qǐng)求到的jsCode* @return 授權(quán)信息~*/@Overridepublic Code2Session getWinXinJson(String jsCode) {// https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_codeStringBuilder url = new StringBuilder();url.append("https://api.weixin.qq.com/sns/jscode2session?appid=");url.append(WeiXinPostParamConstant.APP_ID);url.append("&secret=");url.append(WeiXinPostParamConstant.SECRET);url.append("&js_code=");url.append(jsCode);url.append("&grant_type=authorization_code");try {String weiXinJson = HttpClientUtil.httpGetRequest(url.toString());System.out.println(weiXinJson);return new ObjectMapper().readValue(weiXinJson, Code2Session.class);} catch (Exception e) {e.printStackTrace();}return null;}@Autowiredprivate WeiXinUserMapper userMapper;public WeiXinUser getWeiXinUserByOpenId(String openId) {WeiXinUser tmpUser = new WeiXinUser();tmpUser.setWxOpenId(openId);QueryWrapper<WeiXinUser> queryWrapper = new QueryWrapper<>(tmpUser);return userMapper.selectOne(queryWrapper);}@Overridepublic String doLogin(WeiXinUser user) throws Exception {// 登錄需要:// 1. 根據(jù)小程序傳來的openid驗(yàn)證數(shù)據(jù)庫中的id,看是否存在~WeiXinUser weiXInUser = getWeiXinUserByOpenId(user.getWxOpenId());System.out.println("doLogin----->" + weiXInUser);if (weiXInUser != null) {// 2. 存在 返回jwt簽名~ 頁面保存return JwtUtil.createToken(weiXInUser);}// 2. 不存在 return ""return null;}@Overridepublic void addWeiXinUser(WeiXinUser user) {// userMapper.addWeiXinUser(user);userMapper.insert(user);} }

設(shè)置攔截器對(duì)要訪問的方法攔截,并判斷jwt token

增加注解,靈活判斷哪些controlelr方法需要配token驗(yàn)證

package top.bitqian.config;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 要給哪些方法進(jìn)行token驗(yàn)證*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface AuthTokenCheck {}

攔截器

package top.bitqian.config;import com.auth0.jwt.interfaces.Claim; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; import java.util.Map;/*** 攔截器* @author echo lovely* @date 2020/12/5 20:28*/@Configuration public class InterceptorConfig implements WebMvcConfigurer {/*** 攔截器需要被注冊進(jìn)..* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new TokenInterceptor());}}class TokenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {System.out.println("進(jìn)來l...");// 對(duì)方法進(jìn)行攔截if (! (handler instanceof HandlerMethod)) {return true;}// 方法對(duì)象HandlerMethod handlerMethod = (HandlerMethod) handler;Method methodTarget = handlerMethod.getMethod();// 對(duì)加了AuthTokenCheck注解 的方法進(jìn)行token驗(yàn)證~boolean isTokenTarget = methodTarget.isAnnotationPresent(AuthTokenCheck.class);if (isTokenTarget) {// 進(jìn)行token驗(yàn)證, 頭部里面的token// String authorizeToken = request.getHeader("authorize_token");String authorizeToken = request.getParameter("authorize_token");try {Map<String, Claim> claimMap = JwtUtil.parseToken(authorizeToken);// 解析獲取token中的用戶id~ 也可根據(jù)相應(yīng)的鍵獲取其它信息Integer id = claimMap.get("id").asInt();String userName = claimMap.get("userName").asString();System.out.println(id + "\t" + userName);// 放入request中request.setAttribute("id", id);return true;} catch (Exception e) {return false;}}return true;} }

總結(jié)

以上是生活随笔為你收集整理的微信小程序结合Java后端实现登录注册的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。