草庐IT

SpringBoot集成Jwt(详细步骤+图解)

撸码社区 2023-04-10 原文

SpringBoot集成Jwt(详细步骤+图解)

Jwt简介

JSON Web Token是目前最流行的跨域认证解决方案,,适合前后端分离项目通过Restful API进行数据交互时进行身份认证

Jwt构成(.隔开)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MTkxNjQ4NjEsInVzZXJuYW1lIjoiYWRtaW4ifQ.fo5a-H_C7XG3fSnNdCEMzM2QmrF5c7yypzoSxGzgJOo

Header(头部):放有签名算法和令牌类型
Payload(负载):你在令牌上附带的信息:比如用户的姓名,这样以后验证了令牌之后就可以直接从这里获取信息而不用再查数据库了
Signature(签名):对前两部分的签名,防止数据篡改

交互流程

本文将通过几个简单步骤教大家如何集成Jwt,废话不多说,直接上步骤。(注:使用了Lombok,需下载好相关插件及依赖)

  • 在项目的pom文件中加入Jwt依赖
        <!---jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>
  • 在项目的yml文件中配置账号密码
Login:
  username: admin
  password: admin
  • 创建用户实体类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 * @author admin
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    @NotNull(message = "id不能为空")
    private Integer id;

    @NotBlank(message="姓名不能为空")
    @Length(min = 2, max = 4, message = "name 姓名长度必须在 {min} - {max} 之间")
    private String username;

    @NotBlank(message="密码不能为空")
    @Length(min = 5, max = 10, message = "password 密码长度必须在 {min} - {max} 之间")
    private String password;

}
  • 创建Jwt(生成/验证)工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.commons.lang.StringUtils;

import java.util.Calendar;

/**
 * @author admin
 */
public class JWTUtils {

    /**
     * 获取token
     * @param u user
     * @return token
     */
    public static String getToken(User u) {
        Calendar instance = Calendar.getInstance();
        //默认令牌过期时间7天
        instance.add(Calendar.DATE, 7);

        JWTCreator.Builder builder = JWT.create();
        builder.withClaim("userId", u.getId())
                .withClaim("username", u.getUsername());

        return builder.withExpiresAt(instance.getTime())
                .sign(Algorithm.HMAC256(u.getPassword()));
    }

    /**
     * 验证token合法性 成功返回token
     */
    public static DecodedJWT verify(String token) throws MyException {
        if(StringUtils.isEmpty(token)){
            throw new MyException("token不能为空");
        }

        //获取登录用户真正的密码假如数据库查出来的是123456
        String password = "admin";
        JWTVerifier build = JWT.require(Algorithm.HMAC256(password)).build();
        return build.verify(token);
    }

   /* public static void main(String[] args) {
        DecodedJWT verify = verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MTcxMDg1MDAsInVzZXJuYW1lIjoiYWRtaW4ifQ.geBEtpluViRUg66_P7ZisN3I_d4e32Wms8mFoBYM5f0");
        System.out.println(verify.getClaim("password").asString());
    }*/
}
  • 创建Jwt拦截器(拦截所有请求验证token)
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.chentawen.springbootall.util.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

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

/**
 * @author admin
 */
@Slf4j
public class JWTInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String token = request.getHeader("token");
        if(StringUtils.isEmpty(token)){
            throw new MyException("token不能为空");
        }
        try {
            JWTUtils.verify(token);
        } catch (SignatureVerificationException e) {
            log.error("无效签名! 错误 ->", e);
            return false;
        } catch (TokenExpiredException e) {
            log.error("token过期! 错误 ->", e);
            return false;
        } catch (AlgorithmMismatchException e) {
            log.error("token算法不一致! 错误 ->", e);
            return false;
        } catch (Exception e) {
            log.error("token无效! 错误 ->", e);
            return false;
        }
        return true;
    }
}
  • 将拦截器注入到SpirngMVC
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * @author admin
 */
@Configuration
public class IntercaptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                //拦截的路径
                .addPathPatterns("/**")
                //排除登录接口
                .excludePathPatterns("/user/login");
    }
  • 创建Controller进行测试
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author admin
 */
@RestController
@RequestMapping("user")
public class UserLoginController {

    @Value("${Login.username}")
    private String realUsername;

    @Value("${Login.password}")
    private String realPassword;

    @GetMapping("login")
    public String login(String username, String password) {
        if (username.equals(realUsername) && password.equals(realPassword)) {
            User u = new User();
            u.setPassword(password);
            u.setUsername(username);
            return JWTUtils.getToken(u);
        }
        return "登录失败!账号或者密码不对!";
    }

    @GetMapping("test")
    public String test()  {
        return "访问test - API";
    }
}
  • 使用Postman进行测试

登录接口-返回Jwt

测试接口-返回无权限

测试接口-请求头带token,访问成功

有什么疑问可评论区提问! 求点赞!求转发!求收藏!

有关SpringBoot集成Jwt(详细步骤+图解)的更多相关文章

  1. ruby-on-rails - 如何使辅助方法在 Rails 集成测试中可用? - 2

    我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel

  2. ruby-on-rails - 我如何将 Hoptoad 与 DelayedJob 和 DaemonSpawn 集成? - 2

    我一直很高兴地使用DelayedJob习惯用法:foo.send_later(:bar)这会调用DelayedJob进程中对象foo的方法bar。我一直在使用DaemonSpawn在我的服务器上启动DelayedJob进程。但是...如果foo抛出异常,Hoptoad不会捕获它。这是任何这些包中的错误...还是我需要更改某些配置...或者我是否需要在DS或DJ中插入一些异常处理来调用Hoptoad通知程序?回应下面的第一条评论。classDelayedJobWorker 最佳答案 尝试monkeypatchingDelayed::W

  3. jenkins部署1--jenkins+gitee持续集成 - 2

    前置步骤我们都操作完了,这篇开始介绍jenkins的集成。话不多说,看操作1、登录进入jenkins后会让你选择安装插件,选择第一个默认的就行。安装完成后设置账号密码,重新登录。2、配置JDK和Git都需要执行路径,所以需要先把执行路径找到,先进入服务器的docker容器,2.1JDK的路径root@69eef9ee86cf:/usr/bin#echo$JAVA_HOME/usr/local/openjdk-82.2Git的路径root@69eef9ee86cf:/#whichgit/usr/bin/git3、先配置JDK和Git。点击:ManageJenkins>>GlobalToolCon

  4. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  5. ruby - cucumber 特征和步骤定义 - 2

    我是Cucumber测试的新手。我创建了两个特征文件:events.featurepartner.feature并将我的步骤定义放在step_definitions文件夹中:./step_definitions/events.rbpartner.rbCucumber似乎在所有.rb文件中查找步骤信息。有没有办法限制该功能查看特定的步骤定义文件?我之所以要这样做,是因为即使我使用了--guess标志,我也会遇到不明确的匹配错误。我之所以要这样做,有以下几个原因。我正在测试CMS,并希望在不同的功能中测试每种不同的内容类型(事件和合作伙伴)。事件.特征Feature:AddpartnerA

  6. ruby - 如何在 Cucumber 步骤定义中使单词可选? - 2

    我在下面有一个步骤定义,它执行我想要它执行的操作,即它根据“PAGES”哈希的“page”元素检查页面的url。Then(/^Ishould(still)?beatthe"(.*)"page$/)do|still,page|BROWSER.url.should==PAGES[page]end步骤定义用于两者我应该在...页面我应该还在...页面但是,我不需要将“still”传递到block中。我只需要它是可选的以匹配步骤但不传递到block中。我该怎么做?谢谢。 最佳答案 您想将“静止”组标记为非捕获。这是通过使用?:启动组来完成的

  7. 100个python算法超详细讲解:画直线 - 2

    1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva

  8. 三分钟集成 TapTap 防沉迷 SDK(Unity 版) - 2

    三分钟集成Tap防沉迷SDK(Unity版)一、SDK介绍基于国家对上线所有游戏必须增加防沉迷功能的政策下,TapTap推出防沉迷SDK,供游戏开发者进行接入;允许未成年用户在周五、六、日以及法定节假日晚上8:00-9:00进行游戏,防沉谜时间段进入游戏会弹窗进行提示!开发环境要求:Unity2019.4或更高版本iOS10或更高版本Android5.0(APIlevel21)或更高版本🔗Unity集成Demo参考链接🔗UnityTapSDK功能体验APK下载链接二、集成前准备1.创建应用进入开发者后台,按照提示开始创建应用;2.开通服务在使用TDS实名认证和防沉迷服务之前,需要在上面创建的应

  9. H2数据库配置及相关使用方式一站式介绍(极为详细并整理官方文档) - 2

    目录H2数据库入门以及实际开发时的使用1.H2数据库的初识1.1H2数据库介绍1.2为什么要使用嵌入式数据库?1.3嵌入式数据库对比1.3.1性能对比1.4技术选型思考2.H2数据库实战2.1H2数据库下载搭建以及部署2.1.1H2数据库的下载2.1.2数据库启动2.1.2.1windows系统可以在bin目录下执行h2.bat2.1.2.2同理可以通过cmd直接使用命令进行启动:2.1.2.3启动后控制台页面:2.1.3spring整合H2数据库2.1.3.1引入依赖文件2.1.4数据库通过file模式实际保存数据的位置2.2H2数据库操作2.2.1Mysql兼容模式2.2.2Mysql模式

  10. ruby - 如何预期失败的步骤并传递 cucumber 中的失败? - 2

    我们想测试cucumber的步骤定义。我们希望能够检查的一件事是我们期望失败的测试实际上失败了。为此,我们想编写我们知道会失败的场景并将它们添加到我们的测试套件中,但标记或以其他方式表示它们以便当且仅当它们失败时它们“通过”。如何解决这个问题? 最佳答案 您应该测试负面状态。失败的步骤只是通过步骤的倒数。所以做这样的事情:Then/ishouldnotbetrue/dosome_value.should_notbe_trueend这就是我进行失败测试的方式。您还可以捕获异常等,并验证block是否确实抛出该异常lambdadosom

随机推荐