实战SpringBoot集成JWT实现token验证

目录
  • 环境搭建
    • 1、新建一个SpringBoot项目Jwt-Demo,引入项目后面需要用到的jar包
    • 2、数据库结构
    • 3、配置文件application.properties
    • 4、Entity包下新建一个User类
    • 5、Dao包下新建一个UserDao
    • 6、Service包下新建一个USerService
    • 7、UseService的实现类UserServiceImp
    • 8、controller包下新建一个UserController
    • 9、在resource文件夹下新建一个Usermapper文件
    • 10、JWT工具类JwtUtils
  • 引入JWT
    • 登录操作
    • 验证操作
  • 程序优化
    • 测试验证
  • 总结

JWT可以理解为一个加密的字符串,里面由三部分组成:头部(Header)、负载(Payload)、签名(signature)

由base64加密后的header和payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了JWT字符串

往期介绍了JWT相关概念以及基本操作,接下来介绍如何在SpringBoot中整合JWT实现登陆注册

环境搭建

1、新建一个SpringBoot项目Jwt-Demo,引入项目后面需要用到的jar包

  <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--引入mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <!--引入mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
        <!--引入druid数据库连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.1</version>
        </dependency>
        <!--引入lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter-test</artifactId>
            <version>2.1.3</version>
        </dependency>
        <!--引入jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>
    </dependencies>

2、数据库结构

有一个JWT库,里面还有一个User表

3、配置文件application.properties

server.port=8989

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/JWT?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
spring.datasource.username=root
spring.datasource.password=12345678

#mybatis扫描的包
mybatis.type-aliases-package=com.ylc
#mapper文件路径
mybatis.mapper-locations=classpath:/**/*.xml

#开启sql打印日志  logging.level后面是mybatis对应的方法接口所在的包
logging.level.com.ylc.jwtdemo.dao=debug

4、Entity包下新建一个User类

import lombok.Data;

@Data
public class User {
    private  String username;
    private  String password;
    private  int id;
}

5、Dao包下新建一个UserDao

@Mapper
public interface UserDao {

    User login(User user);
}

6、Service包下新建一个USerService

public interface UserService {
    User login(User user);//登录接口
}

7、UseService的实现类UserServiceImp

import java.util.HashMap;
import java.util.Map;

@Service
public class UserServiceImpI implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public User login(User user) {
        User userdb=userDao.login(user);
        if(userdb!=null)
        {
            Map<String,String> map=new HashMap<>();
            map.put("name",userdb.getUsername());
            return userdb;
        }
        throw  new RuntimeException("登录失败");
    }
}

8、controller包下新建一个UserController

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/user/login")
    public Map<String,Object> login(User user)
    {
        log.info("用户名:"+user.getUsername());
        log.info("密码:"+user.getPassword());
        Map<String,Object> map=new HashMap<>();
        try {
            userService.login(user);
            map.put("msg","登录成功");
            map.put("code","200");
        }
        catch (Exception ex)
        {
            map.put("msg","登录失败");
        }

        return map;
    }
}

9、在resource文件夹下新建一个Usermapper文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 指的是要配置的全限定类名-->
<mapper namespace="com.ylc.jwtdemo.dao.UserDao">
    <select id="login" parameterType="com.ylc.jwtdemo.entity.User" resultType="com.ylc.jwtdemo.entity.User">
        select *from user where username=#{username} and password=#{password}
    </select>
</mapper>

10、JWT工具类JwtUtils

/**
 * JWT工具类
 * @author yanglingcong
 * @date 2021/12/31 11:24 AM
 */
public class JwtUtils {
    //鉴权 相当于私钥保存在服务器上
    private  static  final String  secret="##@$%@#S#WS";

    /**
     * 生成token
     * @author yanglingcong
     * @date 2021/12/31 11:23 AM
     * @param map
     * @return String
     */
    public static  String getToken(Map<String,String> map)
    {
        Calendar instance=Calendar.getInstance();
        //默认七天过期
        instance.add(Calendar.DATE,7);
        //创建JWT
        JWTCreator.Builder builder = JWT.create();

        //payload
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });
        //指定令牌过期时间
        builder.withExpiresAt(instance.getTime());

        String token=builder.sign(Algorithm.HMAC256(secret));
        return token;
    }

    /**
     * 验证token
     * @author yanglingcong
     * @date 2021/12/31 11:26 AM
     * @param token
     */
    public  static  DecodedJWT  verify(String token) {
        return  JWT.require(Algorithm.HMAC256(secret)).build().verify(token);
    }

}

整个项目概览

测试验证是否能够连通数据库

访问:localhost:8989/user/login?username=ylc&password=123456

引入JWT

@Slf4j
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/user/login")
    public Map<String,Object> login(User user)
    {
        log.info("用户名:"+user.getUsername());
        log.info("密码:"+user.getPassword());
        Map<String,Object> map=new HashMap<>();
        try {
            userService.login(user);
            map.put("msg","登录成功");
            map.put("code","200");

            Map<String,String> payload=new HashMap<>();
            payload.put("name",user.getUsername());
            String token= JwtUtils.getToken(payload);
            map.put("token",token);
        }
        catch (Exception ex)
        {
            map.put("msg","登录失败");
        }

        return map;
    }

    @PostMapping("/test/verity")
    public  Map<String,String> verityToken(String token)
    {
        Map<String, String> map=new HashMap<>();
        log.info("token为"+token);
        try {
            DecodedJWT verify = JwtUtils.verify(token);
            map.put("msg","验证成功");
            map.put("state","true");
        }
        catch (Exception exception)
        {
            map.put("msg","验证失败");
            exception.printStackTrace();
        }
        return map;
    }
}

登录操作

访问:http://localhost:8989/user/login?username=ylc&password=123456

验证操作

访问:http://localhost:8989/test/verity

但是我们这样写在实际项目中是不合理的,把token生成的代码放在了Controller中,业务逻辑是不能放在Controller层中的。假如很多接口都需要token来进行验证保护,那每一个接口都需要添加这样一段代码,造成代码冗余。

程序优化

如果是web项目使用拦截器进行优化,如果是springcloud项目在网关层进行拦截,下面演示如何使用拦截器拦截

最好还把JWT生成token放在http请求头,这样就不需要把token当成参数传递了

新建一个拦截器JwtInterceptor

/**
 * JWT拦截器
 * @author yanglingcong
 * @date 2021/12/31 12:39 PM
 */
public class JwtInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HashMap<String, String> map=new HashMap<>();
        //从http请求头获取token
        String token = request.getHeader("token");
        try {
            //如果验证成功放行请求
            DecodedJWT verify = JwtUtils.verify(token);
            return true;
        }
        catch (Exception exception)
        {
            map.put("msg","验证失败:"+exception);
        }
        String json = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json:charset=UTF=8");
        response.getWriter().println(json);
        return false;
    }
}

然后把拦截器注册到过滤器中,新建一个过滤器InterceptConfig

/**
 * @author yanglingcong
 */
@Configuration
public class InterceptConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器
        registry.addInterceptor(new JwtInterceptor())
                //拦截的路径 需要进行token验证的路径
                .addPathPatterns("/test/verity")
                //放行的路径
                .excludePathPatterns("/user/login");
    }
}

登录是不需要拦截的,其他请求如果有需要验证token就放入拦截器的路径

测试验证

在http请求头中放入token,会被拦截器拦截验证token的有效性

总结

这就是SpringBoot整合JWT实际项目一个大概的流程,但是细节方面secret(私钥)肯定每个用户都是不一样的,这里给写死了,而且私钥得保存在一个安全的地方。包括payload部分不能存放敏感的密码信息等等,还可以进行优化。

项目代码:https://gitee.com/yanglingcong/jwt-demo

到此这篇关于实战SpringBoot集成JWT实现token验证的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • springboot+jwt实现token登陆权限认证的实现

    一 前言 此篇文章的内容也是学习不久,终于到周末有时间码一篇文章分享知识追寻者的粉丝们,学完本篇文章,读者将对token类的登陆认证流程有个全面的了解,可以动态搭建自己的登陆认证过程:对小项目而已是个轻量级的认证机制,符合开发需求: 二 jwt实现登陆认证流程 用户使用账号和面发出post请求 服务器接受到请求后使用私钥创建一个jwt,这边会生成token 服务器返回这个jwt给浏览器 浏览器需要将带有token的jwt放入请求头 每次手到客户端请求,服务器验证该jwt的token 验证成功返回

  • SpringBoot整合JWT框架,解决Token跨域验证问题

    一.传统Session认证 1.认证过程 1.用户向服务器发送用户名和密码. 2.服务器验证后在当前对话(session)保存相关数据. 3.服务器向返回sessionId,写入客户端 Cookie. 4.客户端每次请求,需要通过 Cookie,将 sessionId 回传服务器. 5.服务器收到 sessionId,验证客户端. 2.存在问题 1.session保存在服务端,客户端访问高并发时,服务端压力大. 2.扩展性差,服务器集群,就需要 session 数据共享. 二.JWT简介 JWT

  • SpringBoot集成JWT生成token及校验方法过程解析

    GitHub源码地址:https://github.com/zeng-xian-guo/springboot_jwt_token.git 封装JTW生成token和校验方法 public class JwtTokenUtil { //公用密钥-保存在服务端,客户端是不会知道密钥的,以防被攻击 public static String SECRET = "ThisIsASecret"; //生成Troke public static String createToken(String u

  • 基于springboot+jwt实现刷新token过程解析

    前一段时间讲过了springboot+jwt的整合,但是因为一些原因(个人比较懒)并没有更新关于token的刷新问题,今天跟别人闲聊,聊到了关于业务中token的刷新方式,所以在这里我把我知道的一些点记录一下,也希望能帮到一些有需要的朋友,同时也希望给我一些建议,话不多说,上代码! 1:这种方式为在线刷新,比方说设定的token有效期为30min,那么每次访问资源时,都会在拦截器中去判断一下token是否过期,如果没有过期就刷新token的时间为30min,反之则会重新登录,需要注意的是这种方式

  • SpringBoot JWT实现token登录刷新功能

    目录 1. 什么是JWT 2. JWT组成部分 3. JWT加密方式 4.实战 5.总结 1. 什么是JWT Json web token (JWT) 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准.简答理解就是一个身份凭证,用于服务识别. JWT本身是无状态的,这点有别于传统的session,不在服务端存储凭证.这种特性使其在分布式场景,更便于扩展使用. 2. JWT组成部分 JWT有三部分组成,头部(header),载荷(payload),是签名(signature). 头

  • SpringBoot整合JWT Token的完整步骤

    目录 背景 一  JWT 消息构成 1.1 组成 1.2 header 1.3 playload 1.4 signature 二 Spring Boot 和 JWT集成实例 2.1 项目依赖 2.2 自定义注解 @JwtToken 2.3 JWT认证工具类 JwtUtil.java 2.4 拦截器拦截带有注解的接口 JwtInterceptor.java 2.5 全局异常捕获 2.6 接口 JwtController.java 2.7 Postman测试接口 2.7.1 在没有token的情况下

  • SpringBoot集成JWT实现token验证的流程

    JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github.com/jwtk/jjwt 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息.因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名. JWT请求流程 1. 用户使

  • 实战SpringBoot集成JWT实现token验证

    目录 环境搭建 1.新建一个SpringBoot项目Jwt-Demo,引入项目后面需要用到的jar包 2.数据库结构 3.配置文件application.properties 4.Entity包下新建一个User类 5.Dao包下新建一个UserDao 6.Service包下新建一个USerService 7.UseService的实现类UserServiceImp 8.controller包下新建一个UserController 9.在resource文件夹下新建一个Usermapper文件

  • SpringBoot集成JWT实现登陆验证的方法详解

    1:首先,我们需要在项目中导入两个依赖: <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifa

  • koa+jwt实现token验证与刷新功能

    JWT JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的.自包含的方式,用于作为JSON对象在各方之间安全地传输信息.该信息可以被验证和信任,因为它是数字签名的. 本文只讲Koa2 + jwt的使用,不了解JWT的话请到这里)进行了解. koa环境 要使用koa2+jwt需要先有个koa的空环境,搭环境比较麻烦,我直接使用koa起手式,这是我使用koa+typescript搭建的空环境,如果你也经常用koa写写小demo,可以点个star,方便~ 安

  • golang中gin框架接入jwt使用token验证身份

    目录 jwt 流程: 1.这里使用开源的 jwt-go 1.token 工具类 2. 使用该中间件 3. controller部分代码 jwt jwt的原理和session有点相像,其目的是为了解决rest api中无状态性 因为rest接口,需要权限校验.但是又不能每个请求都把用户名密码传入,因此产生了这个token的方法 流程: 用户访问auth接口,获取token 服务器校验用户传入的用户名密码等信息,确认无误后,产生一个token.这个token其实是类似于map的数据结构(jwt数据结

  • SpringBoot 使用jwt进行身份验证的方法示例

    这里只供参考,比较使用jwt方式进行身份验证感觉不好,最不行的就是不能退出 登陆时设定多长过期时间,只能等这个时间过了以后才算退出,服务端只能验证请求过来的token是否通过验证 Code: /** * Created by qhong on 2018/6/7 15:34 * 标注该注解的,就不需要登录 **/ @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documente

  • SpringBoot使用JWT实现登录验证的方法示例

    什么是JWT JSON Web Token(JWT)是一个开放的标准(RFC 7519),它定义了一个紧凑且自包含的方式,用于在各方之间以JSON对象安全地传输信息.这些信息可以通过数字签名进行验证和信任.可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对来对JWT进行签名. 具体的jwt介绍可以查看官网的介绍:https://jwt.io/introduction/ jwt请求流程 引用官网的图片 中文介绍: 用户使用账号和面发出post请求: 服务器使用私钥创建一个jwt: 服务器返

随机推荐