微信小程序的配置
application-dev.yml
sky:wechat:appid: wx7c3cfb677bfc2fcasecret: 26fdab94f4910262d2b3648a947fce03
application.yml
- 配置jwt
- 配置秘钥
sky:jwt:# 设置jwt签名加密时使用的秘钥admin-secret-key: itcast# 设置jwt过期时间admin-ttl: 720000000# 设置前端传递过来的令牌名称admin-token-name: token# 设置jwt签名加密时使用的秘钥user-secret-key: itheima# 设置jwt过期时间user-ttl: 720000000# 设置前端传递过来的令牌名称user-token-name: authenticationwechat:appid: ${sky.wechat.appid}secret: ${sky.wechat.secret}
拦截器
拦截微信客户端的所有请求
package com.sky.interceptor;import com.sky.constant.JwtClaimsConstant;
import com.sky.context.BaseContext;
import com.sky.properties.JwtProperties;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** jwt令牌校验的拦截器*/
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {@Autowiredprivate JwtProperties jwtProperties;/*** 校验jwt** @param request* @param response* @param handler* @return* @throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断当前拦截到的是Controller的方法还是其他资源if (!(handler instanceof HandlerMethod)) {//当前拦截到的不是动态方法,直接放行return true;}//1、从请求头中获取令牌String token = request.getHeader(jwtProperties.getUserTokenName());//2、校验令牌try {log.info("jwt校验:{}", token);Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());log.info("当前用户id:", userId);BaseContext.setCurrentId(userId);//3、通过,放行return true;} catch (Exception ex) {//4、不通过,响应401状态码response.setStatus(401);return false;}}
}
在全局配置中新增微信请求拦截器
新增刚刚的拦截器,放行登录请求
package com.sky.config;import java.util.List;/*** 配置类,注册web层相关组件*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {@Autowiredprivate JwtTokenAdminInterceptor jwtTokenAdminInterceptor;@Autowiredprivate JwtTokenUserInterceptor jwtTokenUserInterceptor;/*** 注册自定义拦截器** @param registry*/protected void addInterceptors(InterceptorRegistry registry) {log.info("开始注册自定义拦截器...");registry.addInterceptor(jwtTokenAdminInterceptor).addPathPatterns("/admin/**").excludePathPatterns("/admin/employee/login").excludePathPatterns("/admin/employee/download");registry.addInterceptor(jwtTokenUserInterceptor).addPathPatterns("/user/**").excludePathPatterns("/user/user/login").excludePathPatterns("/user/shop/status");}
}
登录controller
为的是获取openid,返回用户信息
package com.sky.controller.user;import com.sky.constant.JwtClaimsConstant;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
import com.sky.properties.JwtProperties;
import com.sky.result.Result;
import com.sky.service.UserService;
import com.sky.utils.JwtUtil;
import com.sky.vo.UserLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/user/user")
@Api(tags = "C端用户接口")
@Slf4j
public class UserController {private final UserService userService;private final JwtProperties jwtProperties;@Autowiredpublic UserController(UserService userService, JwtProperties jwtProperties) {this.userService = userService;this.jwtProperties = jwtProperties;}/*** 微信小程序登录*/@PostMapping("/login")@ApiOperation(value = "微信小程序登录")public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO) {log.info("微信小程序登录");//微信登录User user = userService.wxLogin(userLoginDTO);// 为微信登录的用户生成tokenMap<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.USER_ID, user.getId());String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);UserLoginVO userLoginVO = UserLoginVO.builder().id(user.getId()).openid(user.getOpenid()).token(token).build();return Result.success(userLoginVO);}
}
service层
@Service
public interface UserService {User wxLogin(UserLoginDTO userLoginDTO);
}
- 请求地址:https://api.weixin.qq.com/sns/jscode2session
参数有四个:appid
:小程序idsecret
:小程序秘钥js_code
:临时登录码grant_type
:固定值 authorization_code
package com.sky.service.impl;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.sky.constant.MessageConstant;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
import com.sky.exception.LoginFailedException;
import com.sky.mapper.UserMapper;
import com.sky.properties.WeChatProperties;
import com.sky.service.UserService;
import com.sky.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
import java.util.HashMap;@Service
@Slf4j
public class UserServiceImpl implements UserService {public static final String WX_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";private WeChatProperties wxProperties;private UserMapper userMapper;@Autowiredpublic UserServiceImpl(WeChatProperties wxProperties, UserMapper userMapper) {this.wxProperties = wxProperties;this.userMapper = userMapper;}/*** 微信小程序登录* @param userLoginDTO 用户登录信息* @return 用户信息*/@Overridepublic User wxLogin(UserLoginDTO userLoginDTO) {log.info("微信小程序登录");String openid = getOpenid(userLoginDTO.getCode());if(openid == null){throw new LoginFailedException(MessageConstant.LOGIN_FAILED);}//3. 根据openid查询用户信息,不存在则新增用户(针对外卖系统来说,不是微信)User user = userMapper.getByOpenid(openid);if(user == null){user = new User();user.setOpenid(openid);user.setCreateTime(LocalDateTime.now());userMapper.insert(user);}//4. 返回用户信息return user;}/*** 获取openid* @param code 微信登录凭证* @return openid*/private String getOpenid(String code) {//1. 调用微信接口获取用户信息 获取openidHashMap<String,String> map = new HashMap<>();map.put("appid",wxProperties.getAppid());map.put("secret",wxProperties.getSecret());map.put("js_code", code);map.put("grant_type","authorization_code");String json = null;try {json = HttpClientUtil.doGet(WX_LOGIN_URL,map );} catch (URISyntaxException | IOException e) {log.error("请求失败", e);throw new RuntimeException(e);}//2. 判断openid是否存在,不存在则抛出异常JSONObject jsonObject = JSON.parseObject(json);return jsonObject.getString("openid");}
}