前言
最近在做毕业设计,涉及到微信小程序的开发,要求前端小程序用户使用微信身份登录,登陆成功后,后台返回自定义登录状态token给小程序,后续小程序发送API请求都需要携带token才能访问后台数据。
本文是对接微信小程序,实现自定义登录状态的一个完整示例,实现了小程序的自定义登陆,将自定义登陆态token返回给小程序作为登陆凭证。用户的信息保存在数据库中,登陆态token缓存在redis中。涉及的技术栈:
- SpringBoot -> 后端基础环境
- Shiro -> 安全框架
- JWT -> 加密token
- MySQL -> 主库,存储业务数据
- MyBatis-Plus -> 操作数据库
- Redis -> 缓存token和其他热点数据
- Lombok -> 简化开发
- FastJson -> json消息处理
- RestTemplate -> 优雅的处理web请求
项目GitHub地址:github.com/gongsir0630…
特性
- 基于WxJava对接微信小程序,实现用户登录、消息处理
- 支持Shiro注解编程,保持高度的灵活性
- 使用JWT进行校验,完全实现无状态鉴权
- 使用Redis存储自定义登陆态token,支持过期时间
- 支持跨域请求
准备工作
基础知识预备:
- 具备SpringBoot基础知识并且会使用基本注解;
- 了解JWT(Json Web Token)的基本概念,并且会简单操作JWT的 JAVA SDK;
- 了解Shiro的基本概念:Subject、Realm、SecurityManager等(建议去官网学习一下)
其他说明:
本文只对shiro和jwt整合进行介绍说明,具体的微信登录实现是使用RestTemplate
调用我自己的wx-java-miniapp
项目,该项目基于WxJava
实现,支持多个小程序登录、消息处理。
本文使用以下调用处理即可:
1 | java复制代码// 1. todo: 微信登录: code + appid -> openId + session_key |
项目地址:
整体思路
先了解一下小程序官方登录流程,官方说明戳这里
- 小程序调用
wx.login()
得到code
,将code发送到后台,后台通过wx-java-miniapp
获取到用户的openId
和session_key
; - 后台通过jwt工具生成自定义用户状态信息
token
,并且后台在数据库中查询openId
判断是否存在,根据查询结果封装不同的消息,最后连同token
一起返回给小程序; - 之后用户访问每一个需要权限的API请求必须在
header
中添加Authorization
字段,后台会进行token
的校验,如果有误会直接返回401
。
token加密说明
- 使用
uuid
随机生成一个jwt-id - 将用户的
openId
、session_key
连同jwt-id
一起,使用小程序的appid
进行签名加密并设置过期时间,最终生成token
- 将
"JWT-SESSION-"+jwt-id
和token
以key-value的形式存入redis
中,并设置相同的过期时间
token校验说明
- 解析token中jwt-id
- 以
"JWT-SESSION-"+jwt-id
为key从redis中获取redisToken - 解析
redisToken
的携带信息,重新以相同的方式生成验证器,同token
进行校验比对
项目实现
- 项目数据库使用
MySQL
作为作为主库,如果是clone
的项目,请在运行之前准备好相应的数据库,并修改配置信息。 - 项目使用了redis缓存,运行前请在本地安装
redis
,使用默认配置即可,无需修改。 - 项目中使用了
lombok
简化开发,请在idea或者eclipse安装lombok插件。
创建Maven项目
新建一个SpringBoot项目,修改pom文件,添加相关dependency:
1 | xml复制代码<?xml version="1.0" encoding="UTF-8"?> |
注意JDK版本:1.8
相关配置 | 工具准备
配置你的application.yml ,主要是配置你的小程序appid和url,还有你的数据库和redis。
1 | yml复制代码# 设置日志级别 |
说明:
appid: 当前小程序的appid
url: wx-java-miniapp项目接口地址
配置fastJson
在启动类中配置fastJson
-> ShiroJwtDemoApplication.java
1 | java复制代码/** |
配置Redis
配置Redis -> RedisConfig.java
1 | java复制代码/** |
配置RestTemplate
配置RestTemplate -> RestTemplateConfig.java
1 | java复制代码/** |
返回集封装
CodeMsg.java
1 | java复制代码/** |
Result.java
1 | java复制代码/** |
异常封装与处理
自定义异常 -> ApiAuthException.java
1 | java复制代码import com.github.gongsir0630.shirodemo.controller.res.CodeMsg; |
全局异常处理 -> AppExceptionHandler.java
1 | java复制代码/** |
准备数据源
- 数据库:shiro-jwt-demo
- 数据表:user
注意:这里是业务数据库,也就是我们小程序用户信息都由我们自己存储,第一次默认使用微信公开信息注册,之后用户可以自行更新这些信息,和微信信息独立开。
创建对应的实体类 -> User.java
1 | java复制代码/** |
使用MyBatis-plus创建mapper接口 -> UserMapper.java
1 | java复制代码/** |
MyBatis-Plus配置 -> MybatisPlusConfig.java
1 | java复制代码/** |
创建User业务接口,这里仅仅演示login -> UserService.java
1 | java复制代码/** |
再创建一个微信登录信息对象,主要用作接收微信的openid和session_key,以及用作shiro认证 -> WxAccount.java
1 | java复制代码 * @author 码之泪殇 GitHub: https://github.com/gongsir0630 |
注意:该类不会用于业务信息交互,所以不需要Mapper与db交互。
微信登录接口,在这里实现与微信服务器的信息交互 -> WxAccountService.java
1 | java复制代码 * @author 码之泪殇 GitHub: https://github.com/gongsir0630 |
接口实现逻辑:
- 从配置文件读取
appid
和url
; - 凭借目标请求地址
path
,例如登录是{url}/wx/user/{appid}/login
; - 参数封装,封装来自小程序的
code
; - 使用
RestTemplate
发起登录请求; - 处理返回集。
代码实现 -> WxAccountServiceImpl.java
1 | java复制代码/** |
构建JWT
jwt工具类,用于生成token签名, token校验 -> JwtUtil.java
1 | java复制代码/** |
Realm配置
创建JwtToken,用于shiro鉴权,需要实现AuthenticationToken
-> JwtToken.java
1 | java复制代码/** |
自定义Shiro的Realm配置,需要在Realm中实现我们自定义的登陆及授权逻辑 -> ShiroRealm.java
1 | java复制代码import com.github.gongsir0630.shirodemo.controller.res.CodeMsg; |
重写filter
所有的请求都会先经过Filter
,所以我们继承官方的BasicHttpAuthenticationFilter
,并且重写方法即可 -> JwtFilter.java
1 | java复制代码import com.github.gongsir0630.shirodemo.wx.vo.JwtToken; |
Shiro核心配置
核心配置 -> ShiroConfig.java
- 配置realm规则链
- 配置访问策略:url和filter
- 开启shiro注解支持
1 | java复制代码import com.github.gongsir0630.shirodemo.filter.JwtFilter; |
验证
实现UserService中的login方法 -> UserServiceImpl.java
1 | java复制代码import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
创建controller,编写测试api -> UserController.java
1 | java复制代码import com.alibaba.fastjson.JSONObject; |
编写小程序测试代码获取code
:
1 | js复制代码wx.login({ |
启动 wx-java-miniapp
项目:
启动shiro-jwt-demo
项目:
Postman测试认证:
携带token访问:
最后
以上就是基于Shiro、JWT实现微信小程序登录完整例子的逻辑过程说明及其实现。
- 完整项目地址:github.com/gongsir0630…
本文转载自: 掘金