SpringBoot集成JWT(极简版)

SpringBoot集成JWT(极简版)

在WebConfig配置类中设置接口统一前缀

import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements  WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 指定controller统一的接口前缀
        configurer.addPathPrefix("/api", clazz -> clazz.isAnnotationPresent(RestController.class));
    }
}

导入JWT依赖

<dependency>
    <groupid>com.auth0</groupid>
    <artifactid>java-jwt</artifactid>
    <version>3.10.3</version>
</dependency>

JWT工具类TokenUtils.java(生成token的工具类)

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.bai.entity.Admin;
import com.bai.service.AdminService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

@Component
@Slf4j
public class TokenUtils {

    private static AdminService staticAdminService;

    @Resource
    private AdminService adminService;

    @PostConstruct
    public void setUserService() {
        staticAdminService = adminService;
    }

    /**
     * &#x751F;&#x6210;token
     *
     * @return
     */
    public static String genToken(String adminId, String sign) {
        return JWT.create().withAudience(adminId) // &#x5C06; user id &#x4FDD;&#x5B58;&#x5230; token &#x91CC;&#x9762;,&#x4F5C;&#x4E3A;&#x8F7D;&#x8377;
                .withExpiresAt(DateUtil.offsetHour(new Date(), 2)) // 2&#x5C0F;&#x65F6;&#x540E;token&#x8FC7;&#x671F;
                .sign(Algorithm.HMAC256(sign)); // &#x4EE5; password &#x4F5C;&#x4E3A; token &#x7684;&#x5BC6;&#x94A5;
    }

    /**
     * &#x83B7;&#x53D6;&#x5F53;&#x524D;&#x767B;&#x5F55;&#x7684;&#x7528;&#x6237;&#x4FE1;&#x606F;
     *
     * @return user&#x5BF9;&#x8C61;
     *  /admin?token=xxxx
     */
    public static Admin getCurrentAdmin() {
        String token = null;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            token = request.getHeader("token");
            if (StrUtil.isNotBlank(token)) {
                token = request.getParameter("token");
            }
            if (StrUtil.isBlank(token)) {
                log.error("&#x83B7;&#x53D6;&#x5F53;&#x524D;&#x767B;&#x5F55;&#x7684;token&#x5931;&#x8D25;&#xFF0C; token: {}", token);
                return null;
            }
            String adminId = JWT.decode(token).getAudience().get(0);
            return staticAdminService.getById(Integer.valueOf(adminId));
        } catch (Exception e) {
            log.error("&#x83B7;&#x53D6;&#x5F53;&#x524D;&#x767B;&#x5F55;&#x7684;&#x7BA1;&#x7406;&#x5458;&#x4FE1;&#x606F;&#x5931;&#x8D25;, token={}", token,  e);
            return null;
        }
    }
}

拦截器JwtInterceptor.java


import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.bai.entity.Admin;
import com.bai.exception.ServiceException;
import com.bai.service.AdminService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

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

@Component
@Slf4j
public class LoginJWTInterceptor implements HandlerInterceptor {

    private static final String ERROR_CODE_401 = "401";

    @Autowired
    private AdminService adminService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        //&#x8FD9;&#x91CC;&#x662F;&#x5224;&#x65AD;&#x6D4F;&#x89C8;&#x5668;&#x8BF7;&#x6C42;&#x5934;&#x91CC;&#x7684;token
        String token = request.getHeader("token");

        if (StrUtil.isBlank(token)) {
            token = request.getParameter("token");
        }

        // &#x6267;&#x884C;&#x8BA4;&#x8BC1;
        if (StrUtil.isBlank(token)) {
            throw new ServiceException(ERROR_CODE_401, "&#x65E0;token&#xFF0C;&#x8BF7;&#x91CD;&#x65B0;&#x767B;&#x5F55;");
        }
        // &#x83B7;&#x53D6; token &#x4E2D;&#x7684;adminId
        String adminId;
        Admin admin;
        try {
            adminId = JWT.decode(token).getAudience().get(0);
            // &#x6839;&#x636E;token&#x4E2D;&#x7684;userid&#x67E5;&#x8BE2;&#x6570;&#x636E;&#x5E93;
            admin = adminService.getById(Integer.parseInt(adminId));
        } catch (Exception e) {
            String errMsg = "token&#x9A8C;&#x8BC1;&#x5931;&#x8D25;&#xFF0C;&#x8BF7;&#x91CD;&#x65B0;&#x767B;&#x5F55;";
            log.error(errMsg + ", token=" + token, e);
            throw new ServiceException(ERROR_CODE_401, errMsg);
        }
        if (admin == null) {
            throw new ServiceException(ERROR_CODE_401, "&#x7528;&#x6237;&#x4E0D;&#x5B58;&#x5728;&#xFF0C;&#x8BF7;&#x91CD;&#x65B0;&#x767B;&#x5F55;");
        }

        try {
            // &#x7528;&#x6237;&#x5BC6;&#x7801;&#x52A0;&#x7B7E;&#x9A8C;&#x8BC1; token
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(admin.getPassword())).build();
            jwtVerifier.verify(token); // &#x9A8C;&#x8BC1;token
        } catch (JWTVerificationException e) {
            throw new ServiceException(ERROR_CODE_401, "token&#x9A8C;&#x8BC1;&#x5931;&#x8D25;&#xFF0C;&#x8BF7;&#x91CD;&#x65B0;&#x767B;&#x5F55;");
        }
        return true;
    }
}

在WebConfig配置类中添加自定义拦截器


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginJWTInterceptor loginJWTInterceptor;

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // &#x6307;&#x5B9A;controller&#x7EDF;&#x4E00;&#x7684;&#x63A5;&#x53E3;&#x524D;&#x7F00;
        configurer.addPathPrefix("/api", clazz -> clazz.isAnnotationPresent(RestController.class));
    }

    // &#x52A0;&#x81EA;&#x5B9A;&#x4E49;&#x62E6;&#x622A;&#x5668;JwtInterceptor&#xFF0C;&#x8BBE;&#x7F6E;&#x62E6;&#x622A;&#x89C4;&#x5219;
    //.excludePathPatterns("/api/admin/login");&#x653E;&#x5F00;&#x767B;&#x5F55;&#x63A5;&#x53E3;&#xFF0C;&#x56E0;&#x4E3A;&#x767B;&#x5F55;&#x7684;&#x65F6;&#x5019;&#x8FD8;&#x6CA1;&#x6709;token
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginJWTInterceptor)  // &#x6DFB;&#x52A0;&#x6240;&#x6709;&#x8DEF;&#x5F84;&#x9700;&#x8981;&#x6821;&#x9A8C;
                .addPathPatterns("/api/**").excludePathPatterns("/api/admin/login", "/api/admin/register");//&#x4E0D;&#x9700;&#x8981;&#x62E6;&#x622A;&#x7684;&#x63A5;&#x53E3;
    }

}

设置自定义头配置(前端在request拦截器设置自定义头)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CrosConfiguration {

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1 &#x8BBE;&#x7F6E;&#x8BBF;&#x95EE;&#x6E90;&#x5730;&#x5740;
        corsConfiguration.addAllowedHeader("*"); // 2 &#x8BBE;&#x7F6E;&#x8BBF;&#x95EE;&#x6E90;&#x8BF7;&#x6C42;&#x5934;
        corsConfiguration.addAllowedMethod("*"); // 3 &#x8BBE;&#x7F6E;&#x8BBF;&#x95EE;&#x6E90;&#x8BF7;&#x6C42;&#x65B9;&#x6CD5;
        source.registerCorsConfiguration("/**", corsConfiguration); // 4 &#x5BF9;&#x63A5;&#x53E3;&#x914D;&#x7F6E;&#x8DE8;&#x57DF;&#x8BBE;&#x7F6E;
        return new CorsFilter(source);
    }
}

Original: https://www.cnblogs.com/b10100912/p/16895982.html
Author: 面向CV工程师
Title: SpringBoot集成JWT(极简版)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/684913/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • PHP——JWT与Token区别

    TOKEN 概念: 令牌,就是加密的字符串, 是访问资源的凭证。Token需要查库验证token 是否有效。 JWT JWT是json web token缩写。它将用户信息加密到t…

    技术杂谈 2023年5月31日
    0122
  • pwm驱动

    1.1、参考博客 参考的教程如下: 1.2、什么是PWM 脉冲宽度调制(PWM),是英文”Pulse Width Modulation”的缩写,简称脉宽调制…

    技术杂谈 2023年6月21日
    0113
  • OAuth2.0基本知识

    前置知识 关注客户端开发者的简易性 通过组织在资源拥有者和HTTP服务商之间的被批准的交互动作代表用户 允许第三方应用代表用户获得访问的权限 为Web应用、桌面应用、手机和起居室设…

    技术杂谈 2023年6月21日
    0111
  • 读经典【1】重构:改善既有代码的设计

    五星好评。很实用。 最近读了重构原版书,同时也在使用其中的一些技巧来改善工作中的项目,自己改完代码会有成就感。 这本书改变了我原有的思想钢印:代码能成功跑起来就不要去动它。实际上,…

    技术杂谈 2023年7月25日
    097
  • 在线互联网地图资源汇总(仅学习用)

    Original: https://www.cnblogs.com/rainbow70626/p/16514207.htmlAuthor: rainbow70626Title: 在…

    技术杂谈 2023年6月1日
    091
  • docker学习:docker镜像

    镜像是什么 镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。 Uni…

    技术杂谈 2023年7月10日
    0123
  • 在工作中学习看问题的角度

    向架构师学习 修改 A 导致 B 出了问题。 我们: 这里是个坑,下次要小心点 也许我应该写文档记录下这件事 也许我应该告诉下其他同事 …… 架构师:从框架…

    技术杂谈 2023年7月11日
    088
  • CentOS 文本编辑器

    Linux 终端的文本编辑器中,较著名的有:Nano、Vim、Emacs。其它文本编辑器还有 Gedit、Sublime,Atom 等等。 1.1、基础命令 nano:打开 nan…

    技术杂谈 2023年7月10日
    0103
  • 哥德尔不完备定理

    自从牛顿用物理的直觉,闯进无穷领域里大胆计算,铸造出犀利无比的分析工具后,许多人凭借着直观想象和聪明,也涌进去推导出许多互相冲突的结论,数学家花了两百多年的时间,才厘清了分析领域里…

    技术杂谈 2023年5月31日
    0100
  • 深入源码理解SpringBean生命周期

    概述 本文描述下Spring的实例化、初始化、销毁,整个SpringBean生命周期,聊一聊BeanPostProcessor的回调时机、Aware方法的回调时机、初始化方法的回调…

    技术杂谈 2023年7月25日
    0104
  • ajax请求地址后加随机数防止浏览器缓存

    看到别人写的JS,ajax请求地址后加随机参数,比如XXXX?t= + new Date().getTime()。 一开始搞不懂为什么,网上查了资料,原因是防止浏览器缓存。浏览器为…

    技术杂谈 2023年6月1日
    0103
  • 2022.20 架构设计随思

    最近在做一个系统的设计,对软件架构设计又有了一些学习思考,就把当下思考认同的一些点记录一下。 需求总是会不断变化,软件架构要根据业务发展不断变化,在做架构设计时不要试图一步到位设计…

    技术杂谈 2023年5月30日
    0102
  • 苞米面C++模板库介绍

    苞米面 C++ 模板库,无需编译,直接包含头文件就可以。所有模板类和算法都包含在 bmm 名字空间里,例如: bmm::recent。需要 C++ 编译器,支持 C++17 标准,…

    技术杂谈 2023年7月23日
    081
  • 各种锁

    只作一个浅显的解释作为区分,具体深入还请搜索相关博客。 可重入锁(又叫递归锁) synchronized&#xFF08;&#x9690;&#x5F0F;&a…

    技术杂谈 2023年7月25日
    0103
  • 一个终端工具竟然有AI功能?使用了1天我立马把其他终端全卸载了!太香了!

    前言 平常工作需要频繁使用终端工具,有一个好的命令行终端工具是非常重要的。 尤其是使用mac的小伙伴,估计不少人都觉得iterm2才是最好的终端工具。 其实起初我也是这么觉得的,但…

    技术杂谈 2023年7月11日
    0108
  • 图解|从根上彻底理解MySQL的索引

    这是图解MySQL的第4篇文章,这篇文章会让你 明白什么是索引,彻底理解B+树和索引的关系; 彻底理解主键索引、普通索引、联合索引; 了解什么是HASH索引,InnoDB和MyIS…

    技术杂谈 2023年7月23日
    099
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球