深圳外包公司网站,登录背景图片素材,海外推广是什么工作,seo怎么判断网站的好坏微信小程序登录微信用户#xff0c;授权信息#xff0c;相关实体类微信用户表实体类获取微信的token常量抽取httpClient工具#xff0c;用于发送请求获取tokennbplus pom工具类请求微信后台#xff0c;获取openid#xff0c;返回的是json登录或者注册完整业务实现#xf…
微信小程序登录微信用户授权信息相关实体类微信用户表实体类获取微信的token常量抽取httpClient工具用于发送请求获取tokennbplus pom工具类请求微信后台获取openid返回的是json登录或者注册完整业务实现登录成功返回jwt签名cotroller实现业务实现设置拦截器对要访问的方法拦截并判断jwt token增加注解灵活判断哪些controlelr方法需要配token验证拦截器登录微信api 后台获取微信token包括openid在内
登录流程
1. 小程序发起wx.login请求获取jscode
2. 获取jscode发送到自己的后端
3. 自己的后台发请求带上jscode, appid(当前用户的唯一标识), secretkey到微信的后端获取session_key, openid
4. 返回session_key或者openid到页面
5. 页面再发请求到后台验证openid 是否存在, 存在即登录。
不存在 保存openid到个人数据库即注册。
6. 登录成功后返回jwt token签名
7. 页面通过微信app.js 的globalData保存openidjwt token信息微信用户授权信息相关实体类
微信用户表
create table forum_info.wei_xin_user
(id int auto_increment primary key,user_name varchar(30) null,user_pwd varchar(30) null,# 这里的密码没用登录只是验证open_id, # 所以说小程序登录是不需要密码的额。它问你是否授权。# 然后收集你的其它个人信息。create_date date null,wx_open_id varchar(30) null
);
实体类
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* 微信用户注册实体类~* /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* 调用微信接口 返回授权信息~* /p* author echo lovely* date 2020/12/4 21:56*/Data
NoArgsConstructor
AllArgsConstructor
public class Code2Session {//用户唯一标识private String openid;// 会话密钥private String session_key;// 用户在开放平台的唯一标识符private String unionid;// 错误码private Integer errcode;// 错误信息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 小程序开发者官网生成;/*** 小程序 appSecret*/public static String SECRET 小程序开发者官网生成;/*** 登录时获取的 code*/public static String JS_CODE ;/*** 授权类型此处只需填写 authorization_code* grant_type ctrl shit u*/public static String GRANT_TYPE ;}
httpClient工具用于发送请求获取token
nbplus pom
这里是boot省略了version
!-- http工具类 --!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --dependencygroupIdorg.apache.httpcomponents/groupIdartifactIdhttpclient/artifactId!--version4.5.6/version--/dependency!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore --dependencygroupIdorg.apache.httpcomponents/groupIdartifactIdhttpcore/artifactId!--version4.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;// 连接超时毫秒 ps表示建立连接的超时时间private final static int SOCKET_TIMEOUT 10000;// 传输超时毫秒 ps表示数据传输处理时间private final static int REQUESTCONNECT_TIMEOUT 2000;// 从线程池获取连接超时时间毫秒private final static int MAX_TOTAL 50;// 线程池的最大连接数private final static int CONNECT_DEFAULT_ROUTE 5;// 每个路由默认基础的连接数private static void init() {if (connectionManager null) {connectionManager new PoolingHttpClientConnectionManager();connectionManager.setMaxTotal(MAX_TOTAL);// 整个连接池最大连接数// 可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间如果超过释放socket重新建立//connectionManager.setValidateAfterInactivity(50000);connectionManager.setDefaultMaxPerRoute(CONNECT_DEFAULT_ROUTE);// 每路由最大连接数默认值是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, MapString, Object params) throws Exception {URIBuilder ub new URIBuilder();ub.setPath(url);ArrayListNameValuePair pairs covertParams2NVPS(params);ub.setParameters(pairs);HttpGet httpGet new HttpGet(ub.build());return getResult(httpGet);}public static String httpGetRequest(String url, MapString, Object headers, MapString, Object params) throws Exception {URIBuilder ub new URIBuilder();ub.setPath(url);ArrayListNameValuePair pairs covertParams2NVPS(params);ub.setParameters(pairs);HttpGet httpGet new HttpGet(ub.build());for (Map.EntryString, 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, MapString, Object params) throws Exception {HttpPost httpPost new HttpPost(url);ArrayListNameValuePair 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 a3b2 形式* param headers 请求头* param params 参数* return* throws IOException*/public static String httpPostRequest(String url, MapString, Object headers, MapString, Object params) throws Exception {HttpPost httpPost new HttpPost(url);for (Map.EntryString, Object param : headers.entrySet()) {httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));}ArrayListNameValuePair pairs covertParams2NVPS(params);httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));return getResult(httpPost);}private static ArrayListNameValuePair covertParams2NVPS(MapString, Object params) {ArrayListNameValuePair pairs new ArrayListNameValuePair();for (Map.EntryString, Object param : params.entrySet()) {pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue())));}return pairs;}/*** post** param url JSON 形式* param headers 请求头* param params 参数* return* throws IOException*/public static String httpPostRequest(String url, MapString, Object headers, String jsonParams) throws Exception {HttpPost httpPost new HttpPost(url);for (Map.EntryString, 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请求** 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) {// 连接超时异常logger.error(connect timeout {}, e);} catch (SocketTimeoutException e) {// 读取超时异常logger.error(read timeout {}, e);} catch (ClientProtocolException e) {// 该异常通常是协议错误导致:比如构造HttpGet对象时传入协议不对(将http写成htp)or响应内容不符合logger.error(protocol exception {}, e);} catch (ParseException e) {// 解析异常logger.error(parse exception {}, e);} catch (IOException e) {// 该异常通常是网络原因引起的,如HTTP服务器未启动等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();作用就是将用完的连接释放下次请求可以复用//这里特别注意的是如果不使用in.close();而仅仅使用response.close();结果就是连接会被关闭并且不能被复用这样就失去了采用连接池的意义。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);}
}
请求微信后台获取openid返回的是json
json转实体类用 dependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactId/dependency/*** 获取openid session_key* param jsCode 小程序请求到的jsCode* return 授权信息~*/Overridepublic Code2Session getWinXinJson(String jsCode) {// https://api.weixin.qq.com/sns/jscode2session?appidAPPIDsecretSECRETjs_codeJSCODEgrant_typeauthorization_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_typeauthorization_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;}登录或者注册完整业务实现登录成功返回jwt签名
我的java json web token签名实现工具类
cotroller实现
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;// 调用微信的接口获取 app_idRequestMapping(/getCode/{jsCode})public Code2Session getWinXinJson(PathVariable(jsCode) String jsCode) {return weiXinUserService.getWinXinJson(jsCode);}// 用户提交wx_id 过来注册RequestMapping(/wx_user/register)public boolean doRegister(WeiXinUser user) {// 账号存在..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);}AuthTokenCheckRequestMapping(/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;}}
业务实现
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* 服务实现类* /p** author echo lovely* since 2020-12-04*/
Service
public class WeiXinUserServiceImpl extends ServiceImplWeiXinUserMapper, WeiXinUser implements WeiXinUserService {/*** 获取openid session_key* param jsCode 小程序请求到的jsCode* return 授权信息~*/Overridepublic Code2Session getWinXinJson(String jsCode) {// https://api.weixin.qq.com/sns/jscode2session?appidAPPIDsecretSECRETjs_codeJSCODEgrant_typeauthorization_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_typeauthorization_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);QueryWrapperWeiXinUser queryWrapper new QueryWrapper(tmpUser);return userMapper.selectOne(queryWrapper);}Overridepublic String doLogin(WeiXinUser user) throws Exception {// 登录需要// 1. 根据小程序传来的openid验证数据库中的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);}
}
设置拦截器对要访问的方法拦截并判断jwt token
增加注解灵活判断哪些controlelr方法需要配token验证
package top.bitqian.config;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 要给哪些方法进行token验证*/
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 {/*** 拦截器需要被注册进..* 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(进来l...);// 对方法进行拦截if (! (handler instanceof HandlerMethod)) {return true;}// 方法对象HandlerMethod handlerMethod (HandlerMethod) handler;Method methodTarget handlerMethod.getMethod();// 对加了AuthTokenCheck注解 的方法进行token验证~boolean isTokenTarget methodTarget.isAnnotationPresent(AuthTokenCheck.class);if (isTokenTarget) {// 进行token验证, 头部里面的token// String authorizeToken request.getHeader(authorize_token);String authorizeToken request.getParameter(authorize_token);try {MapString, Claim claimMap JwtUtil.parseToken(authorizeToken);// 解析获取token中的用户id~ 也可根据相应的键获取其它信息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;}
}