实现 jwt 鉴权- SpringBoot + 微服务

目录

项目结构

主要步骤

auth-service里:

1. 配置 pom.xml 依赖

2. 实现HandlerInterceptor 接口的 preHandle 函数

3. 实现 WebMvcConfigurer 的 addInterceptors 接口

4. 生成 token 和验证 token

5. 登录接口示例

user-service 里:

6. 实现拦截:以 user-service 为例


ps:项目源码等该项目课程答辩结束后会贴出,到时候可以看看源码会更清晰

项目结构

以 jwt 鉴权服务auth-service和 user-service 用户服务为例,auth-service 和 user-service 两个项目位于目录同级,项目结构如下

主要步骤

auth-service里:

1. 配置 pom.xml 依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.10.0</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency></dependencies>
2. 实现HandlerInterceptor 接口的 preHandle 函数
    • 注意加 @Component
    • preHandle 会拦截指定路径的请求,若验证成功返回了 return true ,然后该接口自己会再转发到对应接口处理请求,如果我们return false了就不会继续转发请求
package com.example.authservice.interceptors;import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.example.authservice.utils.JWTUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;@Component
public class JWTInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("*****************************************");System.out.println("开始token验证");System.out.println("*****************************************");Map<String, Object> map = new HashMap<>();// 获取请求头中令牌String token = request.getHeader("token");try {// 验证令牌JWTUtils.verify(token);System.out.println("*****************************************");System.out.println("token验证成功");System.out.println("*****************************************");return true;} catch (SignatureVerificationException e) {e.printStackTrace();map.put("msg","无效签名!");}catch (TokenExpiredException e){e.printStackTrace();map.put("msg","token过期!");}catch (AlgorithmMismatchException e){e.printStackTrace();map.put("msg","token算法不一致!");}catch (Exception e){e.printStackTrace();map.put("msg","token无效!!");}System.out.println("*****************************************");System.out.println("未通过token验证");System.out.println("*****************************************");// 未通过验证:设置状态map.put("state",false);// 将map转为json  jacksonString json = new ObjectMapper().writeValueAsString(map);response.setContentType("application/json;charset=UTF-8");response.getWriter().println(json);return false;}
}
3. 实现 WebMvcConfigurer 的 addInterceptors 接口
  • 注册前面写的拦截器
    • 指定拦截路径 .addPathPatterns 和不拦截路径 .excludePathPatterns
  • 注意:
    • 拦截所有路径要用 /** ——两个*,不要写成一个了!!!
    • 记得加 @Configuration
  • 一般登录接口不拦截
    • 登录接口可以也写在 auth-service 服务中,更方便
      • ps:我本来写在 user-service 里的,本地运行也没问题,但是当我 maven 打包时一直会出现找不到 auth-service 这个模块(具体是 login 接口需要调用JWTUtils 的接口进行 token 验证,这里一直报错找不到这个 import),可是我明明 user-service 里已经添加依赖了,试了网上方法都不行。于是放弃,直接将 login 接口写在 auth-service 里,就避免了在 user-service 里直接调用 suth-service 的接口,但还是需要添加 suth-service 依赖的,因为要实现请求拦截,后面也会说到,这个时候再 maven 打包就可以了,有点玄学在的、、、
package com.example.authservice.config;import com.example.authservice.interceptors.JWTInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
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 InterceptorConfig implements WebMvcConfigurer {@Autowiredprivate JWTInterceptor jWTInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(jWTInterceptor).addPathPatterns("/user/**").excludePathPatterns("/auth/login");}
}
4. 生成 token 和验证 token
  • 此处 SHA256 加密
  • getToken(Map<String,String> map)函数生成 token,代码注释写了,一个萝卜一个坑按需填空即可
  • 验证 token 合法性的函数照抄就好
package com.example.authservice.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.util.Calendar;
import java.util.Map;public class JWTUtils {private static final String SIGNATURE = "!@#$SGW^HDY*%G";/*** 生成token*/public static String getToken(Map<String,String> map){// 默认7天过期Calendar instance = Calendar.getInstance();instance.add(Calendar.DATE,7);// 创建jwt builderJWTCreator.Builder builder = JWT.create();// 设置payloadmap.forEach(builder::withClaim);// 指定令牌过期时间return builder.withExpiresAt(instance.getTime()).sign(Algorithm.HMAC256(SIGNATURE));}/*** 验证token合法性*/public static DecodedJWT verify(String token){return JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);}
}

5. 登录接口示例

写在 auth-service 里,主要逻辑就是在 controller 层,示例如下

package com.example.authservice.controller;import com.example.authservice.utils.JWTUtils;
import com.example.authservice.service.AuthService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.HashMap;
import java.util.Map;@Api(tags = {"登录鉴权接口文档"})
@RestController
@RequestMapping("/auth")
@EnableSwagger2
public class AuthController {@Autowiredprivate AuthService authService;@PostMapping("/login")@ResponseBodypublic Map<String,Object> login(String SID, String SPassword) {Map<String, Object> result = new HashMap<>();if(authService.login(SID, SPassword)){Map<String, String> payLoad = new HashMap<>();payLoad.put("id", SID);String token = JWTUtils.getToken(payLoad);result.put("token", token);result.put("state", true);result.put("msg", "登录成功!");}else {result.put("state","false");result.put("msg", "登录失败!");}return result;}
}

user-service 里:

6. 实现拦截:以 user-service 为例

要实现拦截需要以下步骤:

  • user-service 的 pom.xml 里配置 auth-service 依赖
    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--JWT--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.10.0</version></dependency><!-- 添加对authservice模块的依赖 --><dependency><groupId>com.example</groupId><artifactId>auth-service</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- 排除继承自authservice模块的该依赖,否则会冲突--><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><exclusions><exclusion><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId></exclusion></exclusions></dependency></dependencies>
  • 服务启动类上把 auth-service 加上,这样才能扫描到这个包,但是注意,@SpringBootApplication 本来是默认扫描该启动类对应的包的,如果加了指定扫描包选项,那么也要把这个启动类自己对应的那个包写上,不然自己都扫描不到了,即:
@SpringBootApplication(scanBasePackages={"com.example.userservice", "com.example.authservice"})

参考:

jwt 鉴权参考:

深入浅出JWT的token鉴权机制_jwtutils.token_header-CSDN博客

FrameWork/springbootjwt at master · EamonHu/FrameWork · GitHub

拦截器不起作用看这篇:

Spring Boot 拦截器无效,不起作用_判断拦截器是否起作用-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/802105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python-VBA函数之旅-ascii函数

ascii函数在Python中主要用于将对象(特别是字符和字符串)转换为它们的ASCII表示形式。这种转换在处理文本数据、调试代码以及确保文本以 ASCII 格式存储或传输时非常有用。常见应用场景有&#xff1a; 1、调试和文本处理&#xff1a;当处理包含非ASCII字符(如Unicode字符)的文…

从概念到实践:揭开枚举与联合体在数字化创新时代的神秘面纱

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看&#xff0c;已成习惯 创作不易&#xff0c;多多支持&#xff01; 在编程的世界中&#xff0c;枚举和联合体是两种非常基础且重要的数据结构。它们各自具有独特的特点和用途&#xff0c;为程序员提供…

S参数介绍:双端口和四端口S参数有哪些

信号在传输过程中&#xff0c;并非完全不变&#xff0c;而是存在一定的损耗和变化。这类似于光的折射现象&#xff0c;在信号传输过程中&#xff0c;一部分信号会在输入端被反射回来&#xff0c;一部分信号会被传输到其它端口&#xff0c;还有一部分信号会在传输过程中被耗散。…

ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(三)

本系列文章主要针对ROS机器人常使用的未知环境自主探索功能包explore_lite展开全源码的详细解析&#xff0c;并进行概括总结。 本系列文章共包含六篇文章&#xff0c;前五篇文章主要介绍explore_lite功能包中 explore.cpp、costmap_tools.h、frontier_search.cpp、costmap_clie…

Linux输出输入重定向

输出重定向 # echo 是打印内容 输出重定向&#xff0c;将123写进1.txt文件中 [rootlocalhost ~]# echo 123 > 1.txt # 将services文件的前5行写进1.txt中 [rootlocalhost ~]# head -5 services > 1.txt注意&#xff1a;输出重定向会先清空文件的内容&#xff0c;再进行写…

C语言-函数指针-快速排序算法(书籍示例-入门)

概述 使用C语言&#xff0c;实现结构体多元素&#xff0c;排序算法&#xff08;冒泡排序&#xff09;&#xff0c;这里使用示例&#xff1a;书籍示例讲解 函数简介 函数声明 void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*)) 参…

初识23种设计模式:分类、原理与实际应用

目录 1. 简介2. 设计模式的分类概述3. 设计模式详解3.1 创建型模式&#xff08;共5种&#xff09;3.1.1 单例模式&#xff08;Singleton&#xff09;3.1.2 工厂方法模式&#xff08;Factory Method&#xff09;3.1.3 抽象工厂模式&#xff08;Abstract Factory&#xff09;3.1.…

oracle 中的大页无法使用问题

oracle 中的大页问题 今天巡检数据库的时候&#xff0c;发现有一个备库节点上的负载很大。这个备库基本无人使用。仅做延时查询使用&#xff0c;按理来说不应该有这么大负载&#xff0c; 环境说明 11.2.0.4 单节点dg库。 问题 大页不生效。且数据库所在服务器负载极大 top…

高并发环境下的实现与优化策略

在现代互联网应用中&#xff0c;高并发处理能力是衡量系统性能和稳定性的关键指标之一。尤其对于电商、社交、在线支付等业务场景&#xff0c;面对瞬间涌入的大规模用户请求&#xff0c;如何保证系统的稳定性和响应速度&#xff0c;对技术架构设计与优化提出了极高要求。本文将…

【Linux】Supervisor 基础

要在Linux上启动Supervisor&#xff0c;你可以按照以下步骤进行操作&#xff1a; 确保你已经安装了Supervisor。使用适合你的Linux发行版的包管理器进行安装。例如&#xff0c;对于Ubuntu&#xff0c;可以运行以下命令安装Supervisor&#xff1a; sudo apt-get update sudo apt…

在Java应用程序中嵌入百度地图的实现方法

在许多应用程序中&#xff0c;展示地图是一个常见的需求&#xff0c;特别是对于需要展示位置信息或者导航功能的应用。百度地图是一种常用的地图服务&#xff0c;本文将介绍如何在Java应用程序中嵌入百度地图&#xff0c;并提供一个简单易懂的示例代码。 1. 准备工作 在开始之…

Leetcode:283.移动零

题目要求 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nums [0…

OAuth2.0客户端和服务端Java实现

oauth2 引言 读了《设计模式之美》和《凤凰架构》架构安全篇之后&#xff0c;决定写一个OAuth2.0的认证流程的Demo&#xff0c;也算是一个阶段性的总结&#xff0c;具体原理实现见《凤凰架构》(架构安全设计篇)。 涉及到的源码可以从https://github.com/WeiXiao-Hyy/oauth2获…

Digicert 证书

一、简介 在当今数字化时代&#xff0c;网络安全已成为全球关注的焦点。随着网络攻击和数据泄露事件的频发&#xff0c;企业和组织越来越重视保护自己的网络环境。在这种背景下&#xff0c;数字证书成为了确保网络通信安全的关键工具。作为数字证书行业的领导者&#xff0c;Di…

2024.4.9记——C++多线程系列文章(五)之死锁

引言 如果用单一的全局互斥保护所有共享数据&#xff0c;也即锁的粒度过大&#xff0c;例如在共享大量数据的系统中&#xff0c;这么做会消除并发带来的任何性能优势&#xff0c;原因是多线程系统由此受到强制限定&#xff0c;任意时刻都只准许运行其中一个线程&#xff0c;即…

python应援灯牌代码

代码如下 import pygame import sys import random# 初始化Pygame pygame.init()# 设置窗口尺寸 WINDOW_WIDTH 800 WINDOW_HEIGHT 600 window_surface pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption(应援语跑马灯模拟)# 定义颜色 WH…

Web API(六)之正则表达式

Web API(六)之正则表达式 正则表达式正则基本使用元字符边界符量词范围字符类替换和修饰符change 事件判断是否有类正则表达式 正则表达式(Regular Expression)是一种字符串匹配的模式(规则) 使用场景: 例如验证表单:手机号表单要求用户只能输入11位的数字 (匹配)过滤…

利用AI开源引擎:文本自动摘要提取API (可本地化部署)

新闻摘要提取技术是一种高效的自然语言处理技术&#xff0c;它通过算法对新闻文章进行全面的语义理解和分析&#xff0c;自动抽取文章中的关键信息&#xff0c;生成简洁、连贯的摘要文本。该技术在多个领域都有着广泛的应用&#xff0c;下面将深入探讨其主要的应用场景。 开源项…

【接口】HTTP(4)|Session、Cookie、token有什么区别?

HTTP是一种无状态的协议&#xff0c;服务器本身没有记忆功能&#xff0c;无法记住客户端之前是否有发送过请求&#xff0c;因此客户端每次发送的请求都是独立的 无状态&#xff1a;HTTP是一个无状态的协议。这句话里的无状态是什么意思&#xff1f; - 知乎 1、为什么需要cookie…

Rust通用代码生成器莲花,红莲尝鲜版二十二,发布数据库自动反射新功能及其视频

Rust通用代码生成器莲花&#xff0c;红莲尝鲜版二十二&#xff0c;发布数据库自动反射新功能及其视频 Rust 通用代码生成器莲花&#xff0c;红莲尝鲜版二十二&#xff0c;此版本新增了数据库自动反射功能&#xff0c;可以为遗留数据库配上操作软件。此版本增强了模板向导界面的…