在spring端发送微信登录请求

news/2024/10/7 16:28:25 标签: spring, 微信, java

微信小程序的配置

application-dev.yml

sky:
  wechat:
    appid: wx7c3cfb677bfc2fca
    secret: 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: 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:小程序id
  • secret:小程序秘钥
  • 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");
    }
}


http://www.niftyadmin.cn/n/5693053.html

相关文章

C++:图的遍历

一、简介 图的遍历通常有深度优先遍历和广度优先遍历两种方式&#xff0c;这两种遍历次序对无向图和有向图都使用。 本文分别介绍基于邻接矩阵和邻接表的图的深度优先遍历和广度优先遍历&#xff0c;对于邻接矩阵和邻接表不熟悉的可翻阅&#xff1a;C&#xff1a;图的存储结构及…

面向对象编程【JavaScript】

JavaScript 面向对象编程&#xff08;OOP&#xff09;是一种编程范式&#xff0c;旨在通过对象来组织代码&#xff0c;从而使代码更加模块化、可重用和易于维护。JavaScript 是一种动态语言&#xff0c;它支持面向对象编程风格&#xff0c;但与其他传统的面向对象语言&#xff…

个人开发主页

网站 GitHubCSDN知乎豆包Google百度 多媒体 ffmpeg媒矿工厂videolanAPPLE开发者官网华为开发者官网livevideostack高清产业联盟github-xhunmon/VABloggithub-0voice/audio_video_streamingdoom9streamingmediaFourCC-wiki17哥Depth.Love BlogOTTFFmpeg原理介绍wowzavicuesof…

c++ arrayfire库,两个多维数组元素相乘的注意点

在 ArrayFire 中&#xff0c;元素相乘&#xff08;也称为逐元素乘法或哈达玛乘法&#xff09;可以通过 af::mul 函数或者使用重载的 * 运算符来实现。下面是如何使用 ArrayFire 对两个数组进行元素相乘的示例&#xff1a; #include <arrayfire.h> #include <iostream…

Rethinking Graph Neural Networksfor Anomaly Detection

AAAI24 推荐指数 #paper/⭐⭐ (由于这个领域初读&#xff0c;因此给的推荐分可能不好) 个人总结&#xff1a; 其在半监督&#xff08;1%&#xff0c;40%&#xff09;的情况下&#xff0c;使用多通滤波器&#xff0c;将不同滤波器得到的特征拼接起来&#xff0c;来做分类&…

【斯坦福CS144】Lab1

一、实验目的 1.实现一个流重组器——一个将字节流的小块 &#xff08;称为子串或段 &#xff09;按正确顺序组装成连续的字节流的模块&#xff1b; 2.深入理解 TCP 协议的工作方式。 二、实验内容 编写一个名为"StreamReassembler"的数据结构&#xff0c;它负责…

【React】事件机制

事件机制 react 基于浏览器的事件机制自身实现了一套事件机制&#xff0c;称为合成事件。比如&#xff1a;onclick -> onClick 获取原生事件&#xff1a;e.nativeEvent onClick 并不会将事件代理函数绑定到真实的 DOM节点上&#xff0c;而是将所有的事件绑定到结构的最外层…

mysql学习教程,从入门到精通,SQL 复制表(36)

1、SQL 复制表 在 SQL 中&#xff0c;复制表是一个常见的任务&#xff0c;通常用于备份、测试或数据迁移。下面是一个基本的指南&#xff0c;演示如何在不同的 SQL 数据库管理系统中复制表。 1.1. 使用 CREATE TABLE ... AS SELECT ... 语句 这种方法适用于大多数 SQL 数据库…