一张流程图带你学会SpringBoot结合JWT实现登录功能

202 阅读4分钟

🧑‍💻作者名称:DaenCode 🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。 😎人生感悟:尝尽人生百味,方知世间冷暖。 📖所属专栏:SpringBoot实战


在这里插入图片描述


@[toc]

登录流程图

在这里插入图片描述

🌟数据准备

数据库创建

在这里插入图片描述

数据库表创建

在这里插入图片描述

相关SQL语句

/*
 Navicat Premium Data Transfer
 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50709
 Source Host           : localhost:3306
 Source Schema         : demo
 Target Server Type    : MySQL
 Target Server Version : 50709
 File Encoding         : 65001
 Date: 04/08/2023 11:05:33
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `id` int(50) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `user_password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, 'daencode', '123456');
INSERT INTO `sys_user` VALUES (2, '隔壁老王', '123456');
INSERT INTO `sys_user` VALUES (3, '太监小李', '123456');
SET FOREIGN_KEY_CHECKS = 1;

🌟JWT介绍

基本概念

JWT(JsonWebToken)是一种轻量级的跨域身份验证解决方案。通常被用于无状态身份验证机制,将用户信息签名打包进行传输。

结构

组成结构:header.payload.signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • header:头部。包含了算法类型和令牌类型两部分内容。 在这里插入图片描述

  • payload:载荷或者称之为Claims声明。包含用户或者其他实体的信息。其中的数据结构以Key-Value形式存在。通常分为以下3个类别: 在这里插入图片描述

    • 注册声明:预定义信息。如iss(签发者)、exp(过期时间)、sub(主题)等。
    • 公共声明:根据需要自定义的字段,例如用户 ID、角色、权限等。
    • 私有声明:自定义的私有字段,用于双方约定的额外信息。
  • signature:签名。将头部和载荷进行签名,确保数据的完整性和防止篡改。签名需要使用头部中指定的算法和密钥进行计算。其中的your-256-bit-secret为私钥。 在这里插入图片描述 注意:因header和payload部分为base64编码解码,并不是安全的,所以payload中不能放敏感信息。

🌟具体实现

引入相关依赖

引入项目所需要的依赖。

		<!-- JWT相关 -->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.7.0</version>
		</dependency>

配置文件

注意修改数据库用户名、密码以及url中的数据库名称。

#数据库配置
server.port=8080
spring.datasource.password=个人数据库密码
spring.datasource.username=个人数据库用户名
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2b8
#开启控制台打印sql
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#mybatis下划线转驼峰配置
mybatis.configuration.map-underscore-to-camel-case=true
#配置mapper文件扫描
mybatis.mapper-locations=classpath:mapper/*.xml

用户实体类

这里为了节省篇幅。省略了getter、setter方法,请自行生成。

public class User {
    private Integer id;
    private String userName;
    private String password;
   //省略了getter、setter方法
}

登录请求类

将用户登录的参数单独封装成请求类。

public class UserLogin {
    private String username;
    private String password;
    //省略了getter、setter方法
}

Token生成校验工具类

生成Token时通过Jwts.builder来构建jwttoken中的信息,包含主题、用户信息、颁发时间以及签名算法等信息。 校验Token时通过解析出声明来取出相关用户信息。

public class TokenUtils {
    //过期时间
    private static final long EXPIRE_TIME=60000*60*24*7;
    //秘钥
    private static final String PRI_SECRET="daencode";
    //主体
    private static final String SUBJECT="daencode";
    //token生成
    public static String genToken(User user){
        String token=Jwts.builder()
                .setSubject(SUBJECT)//主题
                .claim("username",user.getUserName())
                .claim("id",user.getId())//用户名、id,还可以放其他多个信息。不要放敏感信息
                .setIssuedAt(new Date())//颁发日期
                .setExpiration(new Date(System.currentTimeMillis()+EXPIRE_TIME))
                .signWith(SignatureAlgorithm.HS256,PRI_SECRET)
                .compact();
        return token;
    }
    //token验证
    public static Claims verifyToken(String token){
        try {
            //从token中解析出claims
            Claims claims=Jwts.parser().setSigningKey(PRI_SECRET).parseClaimsJws(token).getBody();
            return claims;
        } catch (ExpiredJwtException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedJwtException e) {
            throw new RuntimeException(e);
        } catch (MalformedJwtException e) {
            throw new RuntimeException(e);
        } catch (SignatureException e) {
            throw new RuntimeException(e);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e);
        }
    }
}

Controller

如果用户登录成功,则返回token。

@Autowired
    private UserService userService;
    @PostMapping("login")
    public JsonData login(@RequestBody UserLogin userLogin){
        //token为空则返回失败,否则返回成功
        String token=userService.login(userLogin);
        return token==null?JsonData.buildError("登录失败"):JsonData.buildSuccess(token);
    }

UserServiceImpl

如果能从数据库查询到当前用户,则使用token工具类根据当前用户生成token。

 @Autowired
    private UserMapper userMapper;
    @Override
    public String login(UserLogin userLogin) {
        User user=userMapper.login(userLogin);
        if (user==null){
            return null;
        }else {
            return TokenUtils.genToken(user);
        }
    }

UserMapper

public interface UserMapper {
    User login(@Param("userLogin") UserLogin userLogin);
}

UserMapper.xml

<select id="login" parameterType="com.shoanjen.redis.model.UserLogin" resultType="com.shoanjen.redis.model.User">
select * from sys_user where user_name=#{userLogin.username} and user_password=#{userLogin.password}
</select>

🌟测试

在这里插入图片描述

🌟写在最后

有关于SpringBoot结合Jwt实现登录功能的内容到这里就结束了。非常感谢大家的观看,如有疑问可在评论区留言。另外,大家都知道哪些登录方案呢?欢迎大家积极讨论!


请添加图片描述