jwt整合springboot

jwt整合springboot

JWT(JSON Web Token)整合Spring Boot主要是用于实现基于token的身份验证和授权,在这种机制中,服务器会为经过身份验证的用户生成一个签名的token,用户在后续的请求中需要携带这个token来证明自己的身份。

以下是JWT整合Spring Boot的主要功能:

  1. 用户认证:用户首次登录时,服务器会验证用户的凭证(如用户名和密码)。如果凭证有效,服务器会生成一个JWT并返回给用户。
  2. 请求授权:当用户进行后续的请求时,需要在请求头中携带JWT。服务器会验证这个JWT,如果验证通过,服务器就会处理用户的请求。否则,服务器会拒绝请求。
  3. 无状态:由于JWT自身包含了用户的身份信息,服务器不需要保存用户的session信息,这使得应用更易于扩展。
  4. 跨域认证:JWT是自包含的,它不依赖于特定的认证方案。无论用户处于哪个域,只要用户的请求中包含了有效的JWT,服务器就能验证用户的身份。

在Spring Boot中整合JWT(JSON Web Token)主要涉及以下几个步骤:

1.添加依赖:

在您的pom.xml或build.gradle文件中,添加JWT和Spring Security的依赖。

        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.19.2</version>
        </dependency>

2.编写JwtUtils,提高代码重用率:

这是一个名为JwtUtils的工具类,它包含两个静态方法:createTokenverifyToken。这个类用于创建和验证JSON Web Tokens (JWTs)。

createToken方法接受一个包含JWT声明的Map作为参数,然后使用这些声明和一个预定义的密钥来创建一个新的JWT。创建的JWT将在一段预定义的时间后过期。

verifyToken方法接受一个JWT作为参数,然后使用预定义的密钥来验证这个JWT。如果JWT是有效的,那么这个方法将返回一个DecodedJWT对象,否则它将抛出一个异常。

完整代码如下:

package com.example.jwtdemo.demos.jwt.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

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

// JwtUtils类用于创建和验证JWT
public class JwtUtils {
    // 过期时间单位:秒,默认半小时过期
    private static final long EXPIRATION = 60 * 30L * 100;
    // 密钥
    private static final String SECRET = "lwh";

    // createToken方法用于创建JWT
    public static String createToken(Map<String, String> claimMap) {
        // 打印过期时间
        System.out.println(EXPIRATION);
        // 打印当前时间戳加上设定的毫秒数
        System.out.println(new Date().getTime()+EXPIRATION);
        // 创建过期时间对象
        Date expiration = new Date(new Date().getTime()+EXPIRATION);
        // 创建一个新的HashMap来存储Jwt头部信息
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        // 创建JWT的构建器
        JWTCreator.Builder builder = JWT.create();
        // 打印创建Token的参数claimMap
        System.out.println("创建Token的参数claimMap:" + claimMap);
        // 使用Lambda表达式创建payload
        claimMap.forEach(builder::withClaim);
        // 打印过期时间
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(expiration));
        // 返回创建的JWT
        return builder.withHeader(map)
                .withExpiresAt(expiration)
                .sign(Algorithm.HMAC256(SECRET));
    }

    // verifyToken方法用于验证JWT
    public static DecodedJWT verifyToken(String token) {
        // 验证JWT
        DecodedJWT verify = JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
        // 打印验证Token的函数得到的Token
        System.out.println("验证Token的函数得到的Token:" + verify.getToken());
        // 打印验证Token的函数得到的Header
        System.out.println("验证Token的函数得到的Header:" + verify.getHeader());
        // 返回验证的JWT
        return verify;
    }
}


3.编写过滤器:

这是一个名为JwtInterceptor的类,它实现了Spring框架的HandlerInterceptor接口。这个类主要用于拦截HTTP请求,验证请求头中的JWT(JSON Web Token),并根据验证结果决定是否放行请求。

以下是对这个类中各个部分的详细介绍:

  1. preHandle方法:这个方法在请求被处理之前被调用。它首先从请求头中获取JWT,然后尝试验证这个JWT。如果JWT验证成功,那么这个方法将返回true,请求将被放行。如果JWT验证失败,那么这个方法将返回false,请求将被拦截,同时向客户端发送一个包含错误信息的JSON响应。
  2. afterCompletion方法:这个方法在请求被处理之后被调用,无论处理过程中是否发生异常。在这个方法中,我们调用了父类HandlerInterceptorafterCompletion方法,但没有进行任何其他操作。
  3. postHandle方法:这个方法在请求被处理之后,但在视图被渲染之前被调用。在这个方法中,我们调用了父类HandlerInterceptorpostHandle方法,但没有进行任何其他操作。

这个类的主要作用是提供JWT的验证功能,它可以被用于保护需要认证的API端点。

完整代码如下:

package com.example.jwtdemo.demos.jwt.utils;

import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

public class JwtInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {
        Map<String,Object> map = new HashMap<>();
        //获取请求头中的令牌
        String token  = request.getHeader("token");
        System.out.println("拦截器中的token是"+token);
        try {
            //验证令牌
            JwtUtils.verifyToken(token);
            //验证成功,放行请求
            return  true;
        }catch (SignatureVerificationException e){
            e.printStackTrace();
            map.put("msg","无效签名");
        }catch (TokenExpiredException e){
            e.printStackTrace();
            map.put("msg","令牌已过期");
        }catch (AlgorithmMismatchException e){
            e.printStackTrace();
            map.put("msg","令牌算法不匹配");
        }catch (Exception e){
            e.printStackTrace();
            map.put("msg","令牌验证失败");
        }
        //设置状态
        map.put("statle",false);
        //将map转化为json
        String json = new ObjectMapper().writeValueAsString(map);
        //相应json数据
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(json);
        return false;

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

}

4.配置过滤器:

这是一个名为JwtConfig的配置类,它实现了Spring框架的WebMvcConfigurer接口。这个类主要用于配置Spring MVC的拦截器。

以下是对这个类中各个部分的详细介绍:

  1. @Configuration注解:这个注解表明这个类是一个配置类,它会被Spring容器特别对待。Spring容器会在启动时自动扫描到这个类,并根据这个类中的配置信息来配置Spring应用程序。
  2. WebMvcConfigurer接口:这个接口提供了一种方式来自定义Spring MVC的配置。通过实现这个接口,您可以覆盖它的方法来添加自定义的配置。
  3. addInterceptors方法:这个方法是WebMvcConfigurer接口的一个方法,它用于添加自定义的拦截器。在这个方法中,我们创建了一个新的JwtInterceptor实例,并将它添加到了拦截器注册表中。
  4. addPathPatterns方法:这个方法用于设置拦截器需要拦截的URL路径模式。在这个例子中,我们设置了"/**",这意味着拦截器将拦截所有的URL路径。
  5. excludePathPatterns方法:这个方法用于设置拦截器需要排除的URL路径模式。在这个例子中,我们设置了"/user/login",这意味着拦截器将不会拦截到这个URL路径。

这个类的主要作用是配置JWT的拦截器,它可以被用于保护需要认证的API端点。

完整代码如下:

// 导入相关的类和接口
import com.example.jwtdemo.demos.jwt.utils.JwtInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

// 使用@Configuration注解标记这个类是一个配置类
@Configuration
/**
 * JwtConfig类实现了WebMvcConfigurer接口,用于配置Spring MVC的拦截器。
 */
public class JwtConfig implements WebMvcConfigurer {
    // 覆盖WebMvcConfigurer接口的addInterceptors方法
    @Override
    /**
     * addInterceptors方法用于添加自定义的拦截器。
     * @param registry 拦截器注册表。
     */
    public void addInterceptors(InterceptorRegistry registry) {
        // 创建一个新的JwtInterceptor实例,并将它添加到拦截器注册表中
        registry.addInterceptor(new JwtInterceptor())
               // 设置拦截器需要拦截的URL路径模式
               .addPathPatterns("/**")
               // 设置拦截器需要排除的URL路径模式
               .excludePathPatterns("/user/login");
    }
}

5.编写properties.yaml:

server:
    port: 8080

spring:
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql:///interface?useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: root

mybatis:
    mapper-locations: classpath:mapper/*.xml
    configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

6.编写实体类:

package com.example.jwtdemo.demos.jwt.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

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

7.使用mybatis Plus(mybatis略过此步骤):

7.1引入依赖:

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>

7.2配置文件(有不用动):

server:
    port: 8080

spring:
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql:///interface?useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: root

mybatis:
    mapper-locations: classpath:mapper/*.xml
    configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

8.编写XML(mybatis Plus略过此步骤):

<?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">
<!-- 用户配置信息 -->
<mapper namespace="com.example.jwtdemo.demos.jwt.mapper.UserMapper">
    <!--User login(User user)-->
    <select id="login" resultType="com.example.jwtdemo.demos.jwt.entity.User">
        select * from user where username = #{username} and password = #{password}
    </select>
</mapper>

9.编写mapper:

package com.example.jwtdemo.demos.jwt.mapper;

import com.example.jwtdemo.demos.jwt.entity.User;
import org.springframework.stereotype.Component;


@Component
public interface UserMapper {
    User login(User user);
}

10.编写Service:

package com.example.jwtdemo.demos.jwt.service;

import com.example.jwtdemo.demos.jwt.entity.User;

public interface UserService  {
    User login(User user);
}

11.编写Service实现:

package com.example.jwtdemo.demos.jwt.service.impl;

import com.example.jwtdemo.demos.jwt.entity.User;
import com.example.jwtdemo.demos.jwt.mapper.UserMapper;
import com.example.jwtdemo.demos.jwt.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
@Service
public class UserServiceImpl implements UserService {
    @Resource
    UserMapper userMapper;

    @Override
    public User login(User user) {
        return userMapper.login(user);
    }
}

12.编写控制器:

这是一个名为UserHandler的控制器类,它处理与用户相关的HTTP请求。这个类使用了Spring的@RestController注解,这意味着它的所有方法都会返回一个对象,这个对象会被自动转换为JSON格式的响应。

以下是对这个类中各个部分的详细介绍:

  1. @RestController注解:这个注解表明这个类是一个控制器,它的所有方法都会返回一个对象,这个对象会被自动转换为JSON格式的响应。
  2. @RequestMapping注解:这个注解用于映射HTTP请求到特定的处理方法。在这个例子中,我们设置了"/user",这意味着这个控制器将处理所有以"/user"开头的URL路径。
  3. @Slf4j注解:这个注解是Lombok库的一部分,它在类中自动创建一个SLF4J(Simple Logging Facade for Java)的日志对象。这个日志对象可以用于记录日志信息。
  4. login方法:这个方法处理"/login"的GET请求。它接受一个User对象作为参数,然后调用userServicelogin方法来验证用户的用户名和密码。如果用户登录成功,那么这个方法将创建一个新的JWT,并将它添加到响应数据中。
  5. test方法:这个方法处理"/other"的POST请求。它从请求头中获取JWT,然后使用JwtUtilsverifyToken方法来验证这个JWT。如果JWT验证成功,那么这个方法将返回一个包含成功消息的响应。

完整代码如下:

// 导入相关的类和接口
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.jwtdemo.demos.jwt.entity.User;
import com.example.jwtdemo.demos.jwt.service.UserService;
import com.example.jwtdemo.demos.jwt.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

// 使用@RestController注解标记这个类是一个控制器
@RestController
// 使用@RequestMapping注解设置这个控制器处理的URL路径
@RequestMapping("/user")
// 使用@Slf4j注解自动创建一个SLF4J的日志对象
@Slf4j
/**
 * UserHandler类是一个控制器,它处理与用户相关的HTTP请求。
 */
public class UserHandler {
    // 使用@Resource注解注入UserService
    @Resource
    UserService userService;

    // 使用@GetMapping注解来处理HTTP GET请求
    @GetMapping("/login")
    /**
     * login方法处理"/login"的GET请求。
     * @param user 包含用户信息的User对象。
     * @return 返回一个包含响应数据的Map。
     */
    public Map<String, Object> login(User user) {
        // 记录用户的用户名和密码
        log.info("用户名: [{}], 密码: [{}]", user.getUsername(), user.getPassword());
        // 创建一个新的HashMap来存储响应数据
        Map<String, Object> map = new HashMap<>();
        try {
            // 创建一个新的HashMap来存储JWT的payload
            Map<String, String> payload = new HashMap<>();
            // 调用userService的login方法来验证用户的用户名和密码
            User login = userService.login(user);
            // 打印登录用户的信息
            System.out.println("用户信息:" + login);
            // 如果用户登录成功
            if (null != login) {
                // 将用户的id,用户名和密码添加到JWT的payload中
                payload.put("id", user.getId() + "");
                payload.put("name", user.getUsername());
                payload.put("password", user.getPassword());
                // 使用JwtUtils的createToken方法来生成JWT
                String token = JwtUtils.createToken(payload);
                // 将登录状态设置为true
                map.put("state", true);
                // 设置响应消息为"登录成功"
                map.put("msg", "登录成功");
                // 将生成的JWT添加到响应数据中
                map.put("token", token);
            }
            }
            catch (Exception e){
                // 如果在登录过程中发生异常
                // 将登录状态设置为false
                map.put("state", false);
                // 设置响应消息为异常的消息
                map.put("msg", e.getMessage());
            }
            // 返回响应数据
            return map;
        }

    @PostMapping("/other")
    /**
     * test方法处理"/other"的POST请求。
     * @param request HttpServletRequest对象,包含了请求的信息。
     * @return 返回一个包含响应数据的Map。
     */
    public Map<String, Object> test(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<>();
        //获取请求头里的token
        String token = request.getHeader("token");
        DecodedJWT verify = JwtUtils.verifyToken(token);
        log.info("[ID]:[{}], [Name]: [{}]",verify.getClaim("id").asString(),verify.getClaim("name").asString());
        map.put("state", true);
        map.put("msg", "请求成功");
        return map;
    }

}

13.数据库表结构:

在这里插入图片描述

14.测试:

14.1:登录测试:

在这里插入图片描述

{
	"msg": "登录成功",
	"state": true,
	"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEiLCJuYW1lIjoid2FuZyIsImlkIjoiMCIsImV4cCI6MTcwMzIzNTQ5M30.KFRpZ6C81LOXXEuv7QJ3BTV14-_K4aHIeYqvf-tUeP0"
}

14.2请求其他接口:

在这里插入图片描述

{
	"msg": "请求成功",
	"state": true
}

15.更换名称:

这是一个名为MyConfig的配置类,它实现了Spring框架的WebMvcConfigurer接口。这个类主要用于配置Spring MVC的CORS(跨源资源共享)。

以下是对这个类中各个部分的详细介绍:

  1. @Configuration注解:这个注解表明这个类是一个配置类,它会被Spring容器特别对待。Spring容器会在启动时自动扫描到这个类,并根据这个类中的配置信息来配置Spring应用程序。
  2. WebMvcConfigurer接口:这个接口提供了一种方式来自定义Spring MVC的配置。通过实现这个接口,您可以覆盖它的方法来添加自定义的配置。
  3. addCorsMappings方法:这个方法是WebMvcConfigurer接口的一个方法,它用于添加CORS映射。在这个方法中,我们添加了一个新的CORS映射,允许所有的URL路径,允许来自http://example.com的跨域请求,允许GET、POST、PUT和DELETE方法,以及允许"MyCustomToken"、"Content-Type"和"X-Requested-With"请求头。

这个类的主要作用是配置CORS,它可以被用于允许来自特定源的跨域请求。

完整代码如下:

// 导入相关的类和接口
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

// 使用@Configuration注解标记这个类是一个配置类
@Configuration
/**
 * MyConfig类实现了WebMvcConfigurer接口,用于配置Spring MVC的CORS。
 */
public class MyConfig implements WebMvcConfigurer {

    // 覆盖WebMvcConfigurer接口的addCorsMappings方法
    @Override
    /**
     * addCorsMappings方法用于添加CORS映射。
     * @param registry CORS注册表。
     */
    public void addCorsMappings(CorsRegistry registry) {
        // 添加一个新的CORS映射
        registry.addMapping("/**")
                // 设置允许跨域的域名
                .allowedOrigins("[1](http://example.com)") // 允许跨域的域名
                // 设置允许的请求方法
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法
                // 设置允许的请求头
                .allowedHeaders("MyCustomToken", "Content-Type", "X-Requested-With"); // 允许的请求头
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农泡泡糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值