微信小程序的配置
application-dev.yml
yml
sky:
wechat:
appid: wx7c3cfb677bfc2fca
secret: 26fdab94f4910262d2b3648a947fce03
application.yml
- 配置jwt
- 配置秘钥
yml
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: authentication
wechat:
appid: ${sky.wechat.appid}
secret: ${sky.wechat.secret}
拦截器
拦截微信客户端的所有请求
java
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 {
@Autowired
private 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;
}
}
}
在全局配置中新增微信请求拦截器
新增刚刚的拦截器,放行登录请求
java
package com.sky.config;
import java.util.List;
/**
* 配置类,注册web层相关组件
*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Autowired
private JwtTokenAdminInterceptor jwtTokenAdminInterceptor;
@Autowired
private 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,返回用户信息
java
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;
@Autowired
public 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);
// 为微信登录的用户生成token
Map<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层
java
@Service
public interface UserService {
User wxLogin(UserLoginDTO userLoginDTO);
}
- 请求地址:https://api.weixin.qq.com/sns/jscode2session
参数有四个:appid
:小程序idsecret
:小程序秘钥js_code
:临时登录码grant_type
:固定值 authorization_code
java
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;
@Autowired
public UserServiceImpl(WeChatProperties wxProperties, UserMapper userMapper) {
this.wxProperties = wxProperties;
this.userMapper = userMapper;
}
/**
* 微信小程序登录
* @param userLoginDTO 用户登录信息
* @return 用户信息
*/
@Override
public 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. 调用微信接口获取用户信息 获取openid
HashMap<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");
}
}