SpringBoot整合JWT的入门指南

目录
  • 1.JWT
  • 2.JWT登录执行流程图
  • 3.为什么使用JWT?
  • 4.JWT的组成
  • 5.SpringBoot整合JWT
  • 测试
  • 总结

1.JWT

JWT(JSON Web Token),为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。将用户信息加密到token中,服务器不保存任何用户信息,服务器通过保存的密钥验证token的正确性。

优点

1.简介:可以通过 URL POST 参数或者在 HTTP header 发送,因为数据量小,传输速度也很快;

2.自包含:负载中可以包含用户所需要的信息,避免了多次查询数据库;

3.因为 Token 是以 JSON 加密的形式保存在客户端的,所以 JWT 是跨语言的,原则上任何 web 形式都支持;

4.不需要再服务端保存会话信息,特别适用于分布式微服务;

缺点

1.无法作废已经发布的令牌;

2.不易应对数据过期;

2.JWT登录执行流程图

3.为什么使用JWT?

  • 在传统的用户登录认证中,因为http是无状态的,所以都是采用session+cokokie,用户登录成功,服务端会保存一个session,并给客户端一个sessionId,客户端会把sessionId保存在cookie中,每次请求都会携带sessionId。cookie+session模式是保存在内存中,在分布式服务中会面临session共享问题,随着用户量得增加,开销就越来越大。而JWT不需要在服务端保存会话信息,特别适合分布式微服务。
  • 简洁:可以用过URL,POST参数或者在HTTP Header发送,因为数据量小,传输速度也快
  • JWT支持跨语言
  • 自包含: 载荷中包含了所有用户所需要的信息,避免了多次查询数据库。

4.JWT的组成

JWT由三部分构成,类似于如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJscyIsImV4cCI6MTYyNDU5Nzc5Nn0.4kwT1elZCb_k2D7AxbuFHM35VmBK4PcmLaqHhcHEq4_wVe8GVO8ODypGSKksTs-hraBopBCm2IC9EC2rO-GHng

第一部分为头部(header),承载两部分信息

声明类型(JWT)

声明加密算法,默认为HMAC SHA256

{
  "typ","JWT",
  "alg","HS256"
}

使用Base64加密后

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9

第二部分为payload(载荷),存放有效信息的地方,这些有效信息分为三部分:

  • 标准中注册的声明
  • 公共的声明
  • 私有的声明

其中,标准中注册的声明 (建议但不强制使用)包括如下几个部分 :

  • iss: jwt签发者;
  • sub: jwt所面向的用户;
  • aud: 接收jwt的一方;
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间;
  • nbf: 定义在什么时间之前,该jwt都是不可用的;
  • iat: jwt的签发时间;
  • jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击

公共的声明部分:

公共的声明可以添加任何信息,一般添加用户的相关信息或其他业务需要的必要信息,但不建议添加铭感信息,因为在客户端可解密。

私有的声明部分:

私有的声明是提供者和消费者共同定义的声明,不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

第三部分为signature(签证)

var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

//密钥就是我们定义的secret,加密后得到签证
var signature = HMACSHA256(encodedString, '密钥');

5.SpringBoot整合JWT

引入依赖

  <!--JWT-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>
          <!--StringUtils工具包-->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <!--ConfigurationProperties出现异常-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

配置application.yml文件

server:
  port: 8888
spring:
  jwt:
    #过期时间
    expireTime: 1800000
    #加密密钥
    secret: lsyyp5201314
    #token返回头部
    header: LOGINTOKEN

JWT工具类

package org.best.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Date;

@ConfigurationProperties(prefix = "spring.jwt")
public class JWTUtils {

    public static String header;
    private static String secret;
    private static String expireTime;

    /**
     * 生成token
     * @param sub 用户唯一信息
     * @return token
     */
    public  static   String createToken(String sub){
        return JWT
                .create()
                .withSubject(sub)
                .withExpiresAt(new Date(System.currentTimeMillis()+Long.parseLong(expireTime)))
                .sign(Algorithm.HMAC512(secret));
    }

    /**
     * 根据token获取用户信息
     * @param token
     * @return 用户信息
     */
    public static String validateToken(String token){
        return JWT
                .require(Algorithm.HMAC512(secret))
                .build()
                .verify(token)
                .getSubject();
    }

    /**
     * 检验Token是否需要刷新
     * @param token
     * @return
     */
    public static boolean refreshToken(String token) {
        Date expireDate = null;
        try {
            expireDate = JWT
                    .require(Algorithm.HMAC512(secret))
                    .build()
                    .verify(token)
                    .getExpiresAt();
        } catch (TokenExpiredException e) {
            return true;
        }
        return (expireDate.getTime()-System.currentTimeMillis())<0;
    }

    public void setHeader(String header) {
        this.header = header;
    }

    public String getSecret() {
        return secret;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

    public String getExpireTime() {
        return expireTime;
    }

    public void setExpireTime(String expireTime) {
        this.expireTime = expireTime;
    }
}

自定义拦截器

package org.best.config;

import org.apache.commons.lang.StringUtils;
import org.best.common.TokenIsNullException;
import org.best.common.TokenValidateException;
import org.best.util.JWTUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String logintoken = request.getHeader("LOGINTOKEN");
        //如果token为空
        if (StringUtils.isBlank(logintoken)){
            throw new TokenIsNullException("请登录");
        }
        //校验Token
        String sub = JWTUtils.validateToken(logintoken);
        if (StringUtils.isBlank(sub)){
            throw new TokenValidateException("token校验失败");
        }

        //更新token有效期(生产新token)
        if (JWTUtils.refreshToken(logintoken)){
            String token = JWTUtils.createToken(sub);
            response.setHeader(JWTUtils.header,token);
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

注册拦截器

package org.best.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry
                .addInterceptor(new LoginInterceptor())
                .addPathPatterns("/find")
                .excludePathPatterns("/login");
    }
}

自定义异常

package org.best.common;

/**
 * Token校验异常
 */
public class TokenValidateException extends RuntimeException {
    public TokenValidateException() {
    }

    public TokenValidateException(String message) {
        super(message);
    }
}
package org.best.common;

/**
 * Token为空异常
 */
public class TokenIsNullException extends RuntimeException{
    public TokenIsNullException() {
    }

    public TokenIsNullException(String message) {
        super(message);
    }
}

自定义Controller

package org.best.controller;

import org.best.pojo.User;
import org.best.util.JWTUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;

@RestController
public class LoginController {
    @GetMapping("/login")
    public String login(User user, HttpServletResponse response){
        //这里就不做数据库查询了

        //根据用户id生成token
        String token = JWTUtils.createToken(String.valueOf(user.getId()));
        //将token存入HTTP响应头中
        response.setHeader(JWTUtils.header,token);
        return user.toString();
    }

    @GetMapping("/find")
    public String find(){
        return "success";
    }
}

测试

登录接口

我们来测试下find 接口 ,不带token会出现啥情况

带上token

总结

到此这篇关于SpringBoot整合JWT的文章就介绍到这了,更多相关SpringBoot整合JWT内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot Security整合JWT授权RestAPI的实现

    本教程主要详细讲解SpringBoot Security整合JWT授权RestAPI. 基础环境 技术 版本 Java 1.8+ SpringBoot 2.x.x Security 5.x JWT 0.9.0 创建项目 初始化项目 mvn archetype:generate -DgroupId=com.edurt.sli.slisj -DartifactId=spring-learn-integration-security-jwt -DarchetypeArtifactId=maven-ar

  • Spring Boot 整合 JWT的方法

    1.JWT 是什么? JWT 是一个开放标准,它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法.JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名. 简单来说,就是通过一定规范来生成 token,然后可以通过解密算法逆向解密 token,这样就可以获取用户信息. 优点: 1)生产的 token 可以包含基本信息,比如 id.用户昵称.头像等信息,避免再次查库 2)存储在客户端,不占用服务端的内存资源 缺点: token 是经过 base6

  • Springboot实现Shiro整合JWT的示例代码

    写在前面 之前想尝试把JWT和Shiro结合到一起,但是在网上查了些博客,也没太有看懂,所以就自己重新研究了一下Shiro的工作机制,然后自己想了个(傻逼)办法把JWT和Shiro整合到一起了 另外接下来还会涉及到JWT相关的内容,我之前写过一篇博客,可以看这里:Springboot实现JWT认证 Shiro的Session机制 由于我的方法是改变了Shiro的默认的Session机制,所以这里先简单讲一下Shiro的机制,简单了解Shiro是怎么确定每次访问的是哪个用户的 Servlet的Se

  • Spring boot整合shiro+jwt实现前后端分离

    本文实例为大家分享了Spring boot整合shiro+jwt实现前后端分离的具体代码,供大家参考,具体内容如下 这里内容很少很多都为贴的代码,具体内容我经过了看源码和帖子加了注释.帖子就没用太多的内容 先下载shiro和jwt的jar包 <!-- shiro包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId

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

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

  • 详解SpringBoot+SpringSecurity+jwt整合及初体验

    原来一直使用shiro做安全框架,配置起来相当方便,正好有机会接触下SpringSecurity,学习下这个.顺道结合下jwt,把安全信息管理的问题扔给客户端, 准备 首先用的是SpringBoot,省去写各种xml的时间.然后把依赖加入一下 <!--安全--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-secu

  • SpringBoot整合JWT的入门指南

    目录 1.JWT 2.JWT登录执行流程图 3.为什么使用JWT? 4.JWT的组成 5.SpringBoot整合JWT 测试 总结 1.JWT JWT(JSON Web Token),为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准.将用户信息加密到token中,服务器不保存任何用户信息,服务器通过保存的密钥验证token的正确性. 优点 1.简介:可以通过 URL POST 参数或者在 HTTP header 发送,因为数据量小,传输速度也很快: 2.自包含:负载中可以包含用户

  • 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整合mybatis-plus快速入门超详细教程

    目录 前言 mybatis-plus 简介 mybatis-plus 优点 相关链接 mybatis-plus实例 1.示例项目结构 2.数据库准备 3.pom.xml: 4.application.yml 5.User.java 6.UserMapper.java 7.UserServiceImpl.java 8.测试类 mybatis-plus的crud: 1.insert操作: 2.select操作: 3.update操作: 4.delete操作: 总结 前言 mybatis-plus 简

  • SpringBoot整合JWT的实现示例

    目录 一. JWT简介 二. Java实现JWT(SpringBoot方式整合) JWT总结 一. JWT简介 1. 什么是JWT? JWT(JSON Web Token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准. 它将用户信息加密到token里,服务器不保存任何用户信息.服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证:应用场景如用户登录.JWT详细讲解请见 github:https://github.com/jwtk/jjwt 2. 为什么使用JWT

  • SpringBoot整合minio快速入门教程(代码示例)

    分享一个快速使用springboot整合minio实现文件上传和下载的示例.前提是已经安装并运行minio服务,参考 minio快速入门文档 首先添加Minio的依赖 <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>3.0.10</version> </dependency> 然后写一个contro

  • springboot整合flowable框架入门步骤

    最近工作中有用到工作流的开发,引入了flowable工作流框架,在此记录一下springboot整合flowable工作流框架的过程,以便后续再次使用到时可以做一些参考使用,如果项目中有涉及到流程审批的话,可以使用该框架帮我们实现流程图示化展示的功能,为了快速了解flowable工作流框架的一个使用过程,我们直接步入主题,springboot整合flowable工作流框架的步骤如下: 1.首先创建一个springboot工程,然后引入flowable pom依赖,代码如下: <dependenc

  • Spring Boot整合JWT的实现步骤

    springboot整合jwt步骤: 1.登录时,验证账号和密码成功后,生成jwt,返回给前端: 2.前端接收后保存,再做其他操作,比如增删改查时,同时将jwt传给后端进行验证,如果jwt当做参数一起传给后端,那么每个操作都会有jwt,为了方便,把jwt放到请求头中,通过拦截器来验证. 代码 代码结构图如下,除了常规的controller.entity.mapper和service层,还有两个拦截器和注册拦截器,图中用红字进行注释(这篇文章稍微有点长,因为我把代码都放上来了,结合下边的思路和结构

  • 实战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文件

随机推荐