首页 > 其他分享 >浅尝 JWT 整合到 Spring Boot

浅尝 JWT 整合到 Spring Boot

时间:2023-08-07 10:02:13浏览次数:24  
标签:jwt Spring JWT 浅尝 token user import id

本文,我们将 JWT 整合到 Spring Boot 中。

JWT 是什么?

JWT -> JSON Web Token

JWT 是一种开放标准(RFC 7519),用于在网络应用中传递声明信息。

JWT 到一大优势是它的可扩展性和自包含性。它可以在各个系统之间进行安全传输和验证,因为它包含了所有必要的信息,并且经过签名保证了数据的完整性。JWT 通常用于身份验证和授权机制,比如 Web 应用中通过 JWT 来验证用于的身份,下面我们就来实践一下。

本文的实践案例,基于本人之前的文章 Spring Boot 整合 Swagger 接口文档工具项目。

安装依赖

安装 JWT 依赖:

<!-- 引入jwt-->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.8.2</version>
</dependency>

添加 JWT 处理方法

我们这里使用用户字段 idnamepassword 来创建 token

1. 生成 token

// 生成 token
public static String createToken(User user) {
    Date expireDate = new Date(System.currentTimeMillis() + EXPIRATION * 1000);
    Map<String, Object> map = new HashMap<>();
    map.put("alg", "HS256");
    map.put("typ", "JWT");
    System.out.println(user+"user");
    String token = JWT.create()
            .withClaim("id", user.getId())
            .withClaim("name", user.getName())
            .withClaim("password", user.getPassword())
            .withExpiresAt(expireDate)
            .withIssuedAt(new Date())
            .sign(Algorithm.HMAC256(SECRET));

    return token;
}

2. 验证 token

// 校验 token
public static Map<String, Claim> verifyToken(String token) {
    DecodedJWT jwt = null;
    try {
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        jwt = verifier.verify(token);
    } catch (Exception e) {
        return null;
    }
    return jwt.getClaims();
}

完整的代码如下。我们在包 com.launch.util 下创建 JwtTokenUtils.java 文件:

package com.launch.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.launch.model.User;

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

public class JwtTokenUtils {

    private static final String SECRET = "jwtSECRET"; // 密钥

    private static final long EXPIRATION = 3600L; // 3600 秒

    // 生成 token
    public static String createToken(User user) {
        Date expireDate = new Date(System.currentTimeMillis() + EXPIRATION * 1000);
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        System.out.println(user+"user");
        String token = JWT.create()
                .withClaim("id", user.getId())
                .withClaim("name", user.getName())
                .withClaim("password", user.getPassword())
                .withExpiresAt(expireDate)
                .withIssuedAt(new Date())
                .sign(Algorithm.HMAC256(SECRET));

        return token;
    }

    // 校验 token
    public static Map<String, Claim> verifyToken(String token) {
        DecodedJWT jwt = null;
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
            jwt = verifier.verify(token);
        } catch (Exception e) {
            return null;
        }
        return jwt.getClaims();
    }
}

创建过滤文件

我们紧接着创建拦截的过滤文件。我们在包 com.launch.config.authenticationhandler.jwt 下创建文件 JwtFilter.java

package com.launch.config.authenticationhandler.jwt;

import com.auth0.jwt.interfaces.Claim;
import com.launch.util.JwtTokenUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

// /api/user/secure/* 的文件起作用
@WebFilter(filterName = "JwtFilter", urlPatterns = "/api/user/secure/*")
public class JwtFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;

        response.setCharacterEncoding("UTF-8");

        final String token = request.getHeader("Auth");

        if("OPTIONS".equals(request.getMethod())) { // 是否是 OPTIONS 请求
            response.setStatus(HttpServletResponse.SC_OK);
            chain.doFilter(request, response);
        }
        else {

            if(token == null) {
                response.getWriter().write("no token");
                return;
            }
            Map<String, Claim> userData = JwtTokenUtils.verifyToken(token); // 检验 token
            if(userData == null) {
                response.getWriter().write("token illegal");
                return;
            }

            Integer id = userData.get("id").asInt(); // 获取 id
            String userName = userData.get("name").asString(); // 获取用户名
            String password = userData.get("password").asString(); // 获取密码
            request.setAttribute("id", id); // 设置 id
            request.setAttribute("username", userName); // 设置用户名
            request.setAttribute("password", password); // 设置密码

            chain.doFilter(req, res); // 过滤成功
        }
    }

    @Override
    public  void destroy() {}
}

这个文件做了什么事情呢?

urlPatterns = "/api/user/secure/*" 表示接口 /api/user/secure/* 下的接口需要经过验证才可以访问。

request.getHeader("Auth") 我们通过 request 请求的 header 中获取提前存在字段 Auth 上的 token 值。在真实登陆的时候就会存储进去 Auth 内。

request.setAttribute("id", id); 将获取的 id 值存在 request 请求上。usernamepassword 同理。

为了过滤器能够生效,我们需要在入口类添加注释 @ServletComponentScan(basePackages="com.launch.config.authenticationhandler.jwt")

浅尝 JWT 整合到 Spring Boot_Java

验证

最后,我们验证下 token 是否集成生效。该操作在包 com.lauch.controllerUserController.java 文件中操作。

我们模拟登陆,生成 token

// 用户登陆
@GetMapping("/login")
String login(User user) {
    // jimmy simulation
    //        {
    //            "id": 2,
    //            "name": "Jimmy",
    //            "age": 18,
    //            "password": "123456"
    //        }
    String token = JwtTokenUtils.createToken(user);
    return token;
}

浅尝 JWT 整合到 Spring Boot_java_02

下面我们来获取当前登陆的用户信息。

@GetMapping("/secure/current_registrant")
public String currentRegistrant(HttpServletRequest request) {
    Integer id = (Integer) request.getAttribute("id");
    String username = request.getAttribute("username").toString();
    String password = request.getAttribute("password").toString();
    return "当前用户信息: id="+id+" ,username="+username+" ,password="+password;
}

上面也提及到了,我们是要获取 requestheaderAuth 的值。这里就有 Auth = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMzQ1NiIsIm5hbWUiOiJKaW1teSIsImlkIjoyLCJleHAiOjE2OTExNjA0NjMsImlhdCI6MTY5MTE1Njg2M30.nIP23eI-vgIZC-Fw2FGDQw1GrXlA4mBVBb3vkSFySgc。我们在 postman 上设置,并请求该接口:

浅尝 JWT 整合到 Spring Boot_后端_03

参考

标签:jwt,Spring,JWT,浅尝,token,user,import,id
From: https://blog.51cto.com/u_11966691/6991049

相关文章

  • Spring Boot + k8s = 王炸!
    来源:https://blog.csdn.net/qq_14999375/article/details/123309636前言K8s+SpringBoot实现零宕机发布:健康检查+滚动更新+优雅停机+弹性伸缩+Prometheus监控+配置分离(镜像复用)配置健康检查健康检查类型:就绪探针(readiness)+存活探针(liveness)探针类型:exec(进入容器执行脚本......
  • Docker部署SpringBoot项目微服务
     登录linux服务器,进入目录  usr/local目录,创建两个文件夹使用alt+p快捷键,将windows目录中生成的jar包,拖到linux桌面使用cp命令,将linux桌面中jar包,复制到指定目录cplesson01-0.0.1-SNAPSHOT.jar/usr/local/docker/lesson01使用vi命令,编辑dockerfile,制作镜......
  • nacos系列:spring cloud使用nacos实现配置管理和服务发现
    目录版本说明创建项目版本说明IDEA:2021.3Maven:3.6.3Jdk:17Spring-Boot:2.6.13Spring-Cloud:2021.0.5Spring-Cloud-Alibaba:2021.0.5.0创建项目1、选择SpringInitalizr2、选择需要安装的版本和依赖3、修改pom文件<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns......
  • 12-Spring-Cloud-Security
    一、SpringSecurity认证和授权(一)安全性和SpringSecurity框架​1、从一个安全性应用场景说起​如下图所示,工单的生成需要使用用户的订单记录等数据,而这些数据保存在外部平台中;那么就需要用户将自己在订单管理平台上用户名和密码告诉工单系统,工单系统登录到订......
  • Docker部署SpringBoot项目准备
     创建一个SpringBoot项目测试程序,在Windows中执行java  -jar  xxx.jar查看效果java-jarlesson01-0.0.1-SNAPSHOT.jar主要代码1、pom.xml文件<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0&q......
  • Springboot - mybatis
    目录入门入门1.准备工作(创建springboot工程,数据库表user,实体类user)2.引入Mybatis的相关依赖,配置Mybatis3.编写SQL语句(注解/xml)创建工程时直接引入mybatis依赖:dao层编写mapper:packagecom.chuangzhou.dao;importcom.chuangzhou.pojo.User;importorg.apache.ibati......
  • 一种SpringBoot下Scheduler定时任务优雅退出方案
    背景近期业务中有一个定时任务发现每次服务部署时,偶发性的会触发问题,这里记录一下问题的跟进解决。分析现象该定时任务每2分钟执行一次,完成数据的更新处理。同时服务部署了多个服务器节点,为保证每次只有一个服务器节点上的任务在跑,引入了基于Redis缓存的分布式锁。示例源码@Schedu......
  • spring面试必会
    1.什么是Spring框架?Spring框架有哪些主要模块?Spring是针对bean的生命周期进行管理的轻量级容器,一个控制反转和面向切面的容器框架Spring有七大功能模块:1、CoreCore模块是Spring的核心类库,Core实现了IOC功能。2、AOPApringAOP模块是Spring的AOP库,提供了AOP(拦截器)机制,并提......
  • 8、Spring之基于注解的自动装配
    8.1、场景模拟8.1.1、UserDao接口及实现类packageorg.rain.spring.dao;/***@authorliaojy*@date2023/8/5-18:32*/publicinterfaceUserDao{voidsaveUser();}packageorg.rain.spring.dao.impl;importorg.rain.spring.dao.UserDao;importorg......
  • 【springBoot】搭建多模块项目指南
    二、多环境配置内容①在reources目录下建立多个配置文件②在pom.xml配置profile节点③mvn命令行打包命令,基于参数进行打包替换占位符mvn-Ucleaninstall-Dmaven.test.skip=true-Pprod④将target目录下的jar包copy出来,执行命令启动,使用的就是不同环境的配置进行启动的......