[Spring Cloud] (3)gateway令牌token拦截器

文章目录

    • 集成redis
      • Nacos配置增加
    • redis配置
    • 配置pom
      • redis配置RedisConfig
      • redis序列化工具FastJson2JsonRedisSerializer
      • 测试
    • 令牌校验拦截器
      • nacos配置
      • 拦截器代码
      • 微服务登录接口实现
    • 最终效果-登录接口与数据接口

本文gateway与微服务已开源到gitee
杉极简/gateway网关阶段学习

在Gateway(网关)与微服务架构中,令牌校验器(Token Validator)通常扮演着至关重要的角色,它的作用主要包括:

  1. 身份验证:令牌校验器确保只有拥有有效令牌的用户或服务才能访问微服务。这是保护后端服务的第一道防线。
  2. 权限控制:令牌中可能包含了用户的权限信息,校验器可以检查用户是否有足够的权限来访问特定的资源或执行特定的操作。
  3. 会话管理:在用户与服务之间维护会话状态,确保用户在一段时间内的请求可以关联到同一个会话。
  4. 单点登录(SSO):如果多个微服务共享同一个认证系统,令牌校验器可以帮助实现单点登录,用户只需要登录一次就可以访问所有服务。
  5. 负载减轻:通过在网关层面校验令牌,可以减轻微服务的负担,因为微服务不需要再进行令牌的校验,可以专注于业务逻辑的处理。
  6. 安全性增强:令牌校验器可以确保令牌的传输和使用符合安全标准,比如使用HTTPS传输,确保令牌不被窃取或篡改。
  7. 跨域处理:在网关层面处理跨域资源共享(CORS)问题,确保来自不同域的请求能够正常访问微服务。
  8. 集中管理:通过在网关处统一校验令牌,可以集中管理认证策略和令牌格式,便于维护和更新。
  9. 监控与日志记录:在令牌校验的过程中,可以记录相关的访问日志,便于后续的监控和分析。

令牌校验器通常是集成在API网关中的一个组件,它作为微服务架构中的守门人,确保所有进入微服务网络的请求都是合法和安全的。

集成redis

Nacos配置增加

Nacos中增加如下配置

  redis:host: localhostport: 6379password: 123456timeout: 6000

image.png

redis配置

image.png

配置pom

<!--redis-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

redis配置RedisConfig

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** redis配置** @author fir*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport
{@Bean@SuppressWarnings(value = { "unchecked", "rawtypes" })public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory){RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);ObjectMapper mapper = new ObjectMapper();mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);serializer.setObjectMapper(mapper);// 使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(serializer);// Hash的key也采用StringRedisSerializer的序列化方式template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(serializer);template.afterPropertiesSet();return template;}
}

redis序列化工具FastJson2JsonRedisSerializer

package com.fir.gateway.config.redis;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.util.Assert;import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;/*** Redis使用FastJson序列化** @author fir*/
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;private final Class<T> clazz;public FastJson2JsonRedisSerializer(Class<T> clazz){super();this.clazz = clazz;}@Overridepublic byte[] serialize(T t) throws SerializationException{if (t == null){return new byte[0];}return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);}@Overridepublic T deserialize(byte[] bytes) throws SerializationException{if (bytes == null || bytes.length <= 0){return null;}String str = new String(bytes, DEFAULT_CHARSET);return JSON.parseObject(str, clazz);}public void setObjectMapper(ObjectMapper objectMapper){Assert.notNull(objectMapper, "'objectMapper' must not be null");}protected JavaType getJavaType(Class<?> clazz){return TypeFactory.defaultInstance().constructType(clazz);}
}

测试

通过一下代码进行测试,通过测试redis已经集成成功,详情如下:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;import javax.annotation.Resource;@SpringBootTest
public class RedisTest {@Resourceprivate RedisTemplate<String,Object> redisTemplate;@Testvoid set(){redisTemplate.opsForValue().set("name123", "value123");}@Testvoid get(){Object object = redisTemplate.opsForValue().get("name123");System.out.println(object);}
}

image.png

令牌校验拦截器

image.png

nacos配置

首先在nacos中新增tokenCheckwhiteUrls配置项**,**如下配置:

global:# 全局异常捕捉-打印堆栈异常printStackTrace: true# 令牌头变量名称token: Authorization# 令牌校验tokenCheck: true# 不需要进行过滤的白名单whiteUrls:- /tick/auth/login- /ws

拦截器代码

import com.fir.gateway.config.GlobalConfig;
import com.fir.gateway.config.exception.CustomException;
import com.fir.gateway.config.result.AjaxStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import java.util.List;/*** 令牌token校验拦截器** @author fir*/
@Slf4j
@Component
public class AuthorizationFilter implements GlobalFilter, Ordered {/*** 网关参数配置*/private GlobalConfig globalConfig;@Resourceprivate RedisTemplate<String, Object> redisTemplate;@Autowiredpublic void someComponent(GlobalConfig globalConfig) {this.globalConfig = globalConfig;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("登录信息校验:start");// 判断token是否存在,且是否过期boolean tokenKey = globalConfig.isTokenCheck();if (tokenKey) {// 白名单路由判断ServerHttpRequest request = exchange.getRequest();String path = request.getPath().toString();List<String> whiteUrls = globalConfig.getWhiteUrls();if (!whiteUrls.contains(path)) {String tokenHeader = globalConfig.getTokenHeader();String token = exchange.getRequest().getHeaders().getFirst(tokenHeader);if (token == null || token.isEmpty()) {log.error("token为空");throw new CustomException(AjaxStatus.EXPIRATION_TOKEN);}Object obj = redisTemplate.opsForValue().get(token);if (obj != null) {log.info("登录信息校验:true");} else {log.error("token已失效");throw new CustomException(AjaxStatus.EXPIRATION_TOKEN);}} else {log.info("登录信息校验:true,白名单");}} else {log.info("登录信息校验:true,验证已关闭");}return chain.filter(exchange);}@Overridepublic int getOrder() {return -290;}
}

微服务登录接口实现

微服务同样需要集成redis,集成方式与gateway一样

package com.fir.nacos.controller;import com.alibaba.nacos.common.utils.StringUtils;
import com.fir.nacos.config.result.AjaxResult;
import com.fir.nacos.config.result.AjaxStatus;
import com.fir.nacos.entity.LoginResultDTO;
import com.fir.nacos.service.IAuthService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;/*** @author fir*/
@Slf4j
@Api(tags = "系统接口")
@RestController
@RefreshScope
@RequestMapping("/auth")
public class AuthController {@Resourceprivate IAuthService iAuthService;/*** 用户统一登陆** @param username 用户* @param password 密码* @return 登录信息/登录失败信息*/@ApiOperation("登录接口")@ApiImplicitParams({@ApiImplicitParam(name = "username", value = "用户"),@ApiImplicitParam(name = "password", value = "密码")})@RequestMapping("/login")public AjaxResult login(String username, String password) {LoginResultDTO loginResultDTO;if(StringUtils.isNoneBlank(username) && StringUtils.isNoneBlank(password)){loginResultDTO = iAuthService.login(username, password);}else {return AjaxResult.error(AjaxStatus.NULL_LOGIN_DATA);}return AjaxResult.success(loginResultDTO);}
}
/*** 用户统一登录** @param username 账号* @param password 密码* @return 登录信息*/
@Override
public LoginResultDTO login(String username, String password){LoginResultDTO loginResultDTO = new LoginResultDTO();if(StringUtils.isNoneBlank(username) && StringUtils.isNoneBlank(password)){// 此处简单处理,根据实际的项目做更改if(username.equals("fir") && password.equals("123456")){// 生成 Token (可用多种方式例如jwt,此处不额外集成)String token = "Bearer " + username + "token";ConnectDTO connectDTO = ConnectDTO.builder().name(username).build();Object o = JSONObject.toJSONString(connectDTO);redisTemplate.opsForValue().set(token, o, globalConfig.getTimeNum(), globalConfig.timeUnit);loginResultDTO = LoginResultDTO.builder().token(token).build();}}return loginResultDTO;
}

最终效果-登录接口与数据接口

此时如果不登录,则会被拦截
image.png

此时需要先获取到token之后,在数据接口的访问中,增加一个令牌请求头参数Authorization
image.png
image.png

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

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

相关文章

深度学习驱动的蛋白质设计技术与前沿实践-从基础到尖端应用

在生物信息学、合成生物学、药物研发、生物材料制备等领域&#xff0c;深度学习技术的革新正在重塑蛋白质设计工具的边界&#xff0c;使其从单纯的结构预测跃升至具有创造性的设计层面。RFdiffusion作为美国华盛顿大学David Baker教授团队的最新科研成果&#xff0c;凭借其卓越…

springboot+vue科普知识商城考试论坛交流系统网站

本系统主要是设计出新能源科普网站&#xff0c;基于B/S构架&#xff0c;后台数据库采用了Mysql&#xff0c;可以使数据的查询和存储变得更加有效&#xff0c;可以确保新能源科普网站管理的工作能够正常、高效的进行&#xff0c;从而提高工作的效率。总体的研究内容如下&#xf…

软考之零碎片段记录(十五)+复习巩固(十)

一、学习 1. 多对多关系模式 举例&#xff1a;学生和课程。顾客和商品等。 多对多关系的确立需要有中间表&#xff0c;需要使用两个外键确认表中的唯一数据。 2. 数据库范式 1nf 表中每个字段都是原子性不可查分的。在关系&#xff08;或表&#xff09;中&#xff0c;每一行…

2024年跨境电商展览会,深圳+广州+厦门+宁波等地火力全开!

雨果网CCEE全球跨境电商展览会(深圳) 深圳会展中心(福田) 2024年5月11日-13日 2024第七届全球跨境电商节暨第九届深圳国际跨境电商贸易博览会 2024年 6月15日—17日 在深圳会展中心&#xff08;福田&#xff09; ICBE2024深圳国际跨境电商交易博览会 2024年9月02-04日 …

【leetcode面试经典150题】35.螺旋矩阵(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

云服务器上Docker启动的MySQL会自动删除数据库的问题

一、问题说明 除了常见的情况&#xff0c;例如没有实现数据挂载&#xff0c;导致数据丢失外&#xff0c;还需要考虑数据库是否被攻击&#xff0c;下图 REVOVER_YOUR_DATA 就代表被勒索了&#xff0c;这种情况通常是数据库端口使用了默认端口&#xff08;3306&#xff09;且密码…

【Linux网络编程】UDP协议

UDP协议 1.再谈端口号端口号划分认识知名端口号(Well-Know Port Number)两个问题netstatpidof 2.UDP协议2.1UDP的特点2.2面向数据报2.3UDP的缓冲区2.4UDP使用注意事项2.5基于UDP的应用层协议 喜欢的点赞&#xff0c;收藏&#xff0c;关注一下把&#xff01; 1.再谈端口号 端口…

【力扣】101. 对称二叉树

101. 对称二叉树 题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 提示…

五、书架开发--4.电子书离线缓存功能开发

电子书缓存功能需要用到IndexedDB数据库 为什么需要用到IndexedDB数据库呢&#xff0c;在浏览器中有cookie&#xff0c;不过容量很小不超过4K&#xff1b;H5中增加了localstorage&#xff0c;但是容量还是小&#xff0c;只能存储2.5-10兆之间&#xff0c;同时还不能建立自定义…

Ceph [OSDI‘06]论文阅读笔记

原论文&#xff1a;Ceph: A Scalable, High-Performance Distributed File System (OSDI’06) Ceph简介及关键技术要点 Ceph是一个高性能、可扩展的分布式文件系统&#xff0c;旨在提供出色的性能、可靠性和可扩展性。为了最大化数据和元数据管理的分离&#xff0c;它使用了一…

2024年第十五届蓝桥杯C/C++B组复盘(持续更新)

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 试题A&#xff1a;握手问题问题描述思路 试题B&#xff1a;小球反弹问题描述思路…

CSS导读 (元素显示模式 上)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 三、CSS的元素显示模式 3.1 什么是元素显示模式 3.2 块元素 3.3 行内元素 3.4 行内块元素 3.5 元素…