Spring Security的API Key实现SpringBoot 接口安全

Spring Security的API Key实现SpringBoot 接口安全

Spring Security 提供了各种机制来保护我们的 REST API。其中之一是 API 密钥。API 密钥是客户端在调用 API 调用时提供的令牌。

在本教程中,我们将讨论如何在Spring Security中实现基于API密钥的身份验证。
API Keys
一些REST API使用API密钥进行身份验证。API密钥是一个标记,用于向API客户端标识API,而无需引用实际用户。标记可以作为查询字符串或在请求头中发送。

一 添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

二 验证请求头的API KEY

public class AuthenticationService {private static final String AUTH_TOKEN_HEADER_NAME = "X-API-KEY";private static final String AUTH_TOKEN = "Baeldung";public static Authentication getAuthentication(HttpServletRequest request) {String apiKey = request.getHeader(AUTH_TOKEN_HEADER_NAME);if ((apiKey == null) || !apiKey.equals(AUTH_TOKEN)) {throw new BadCredentialsException("Invalid API Key");}return new ApiKeyAuthentication(apiKey, AuthorityUtils.NO_AUTHORITIES);}
}

在这里,我们检查请求头是否包含 API Key,如果为空 或者Key值不等于密钥,那么就抛出一个 BadCredentialsException。如果请求头包含 API Key,并且验证通过,则将密钥添加到安全上下文中,然后调用下一个安全过滤器。getAuthentication 方法非常简单,我们只是比较 API Key 头部和密钥是否相等。

为了构建 Authentication 对象,我们必须使用 Spring Security 为了标准身份验证而构建对象时使用的相同方法。所以,需要扩展 AbstractAuthenticationToken 类并手动触发身份验证。

三 扩展AbstractAuthenticationToken

为了成功地实现我们应用的身份验证功能,我们需要将传入的API Key转换为AbstractAuthenticationToken类型的身份验证对象。AbstractAuthenticationToken类实现了Authentication接口,表示一个认证请求的主体和认证信息。

public class ApiKeyAuthentication extends AbstractAuthenticationToken {private final String apiKey;public ApiKeyAuthentication(String apiKey,Collection<?extends GrantedAuthority> authorities) {super(authorities);this.apiKey = apiKey;setAuthenticated(true);}@Overridepublic Object getCredentials() {return null;}@Overridepublic Object getPrincipal() {return apiKey;}
}

ApiKeyAuthentication 类是类型为 AbstractAuthenticationToken 的对象,其中包含从 HTTP 请求中获取的 apiKey 信息。在构造方法中使用 setAuthenticated(true) 方法。因此,Authentication对象包含 apiKey 和authenticated字段
在这里插入图片描述

四 创建自定义过滤器

实现思路是从请求头中获取API Key,然后使用我们的配置检查秘钥。在这种情况下,我们需要在Spring Security 配置类中添加一个自定义的Filter。

我们将从实现GenericFilterBean开始。GenericFilterBean是一个基于javax.servlet.Filter接口的简单Spring实现。

public class AuthenticationFilter extends GenericFilterBean {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)throws IOException, ServletException {try {Authentication authentication = AuthenticationService.getAuthentication((HttpServletRequest) request);SecurityContextHolder.getContext().setAuthentication(authentication);} catch (Exception exp) {HttpServletResponse httpResponse = (HttpServletResponse) response;httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);httpResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);PrintWriter writer = httpResponse.getWriter();writer.print(exp.getMessage());writer.flush();writer.close();}filterChain.doFilter(request, response);}
}

我们只需要实现doFilter()方法,在这个方法中我们从请求头中获取API Key,并将生成的Authentication对象设置到当前的SecurityContext实例中。

然后请求被传递给其余的过滤器处理,接着转发给DispatcherServlet最后到达我们的控制器。

五 配置类

通过创建建一个SecurityFilterChain bean,可以通过编程方式把我们上面编写的自定义过滤器(Filter)进行注册。

我们需要在 HttpSecurity 实例上使用 addFilterBefore() 方法在 UsernamePasswordAuthenticationFilter 类之前添加 AuthenticationFilter。

@Configuration
@EnableWebSecurity
public class SecurityConfig {@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/**").authenticated().and().httpBasic().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().addFilterBefore(new AuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);return http.build();}}

六 测试

  1. controller
@RestController
public class ResourceController {@GetMapping("/home")public String homeEndpoint() {return "Baeldung !";}
}
  1. 启动类
    禁用 Auto-Configuration
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class})
public class ApiKeySecretAuthApplication {public static void main(String[] args) {SpringApplication.run(ApiKeySecretAuthApplication.class, args);}
}
  1. 测试
curl --location --request GET 'http://localhost:8080/home'

结果返回401
请求头中加上API Key后,再次请求

curl --location --request GET 'http://localhost:8080/home' \
--header 'X-API-KEY: Baeldung'

结果返回200

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

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

相关文章

CSP初赛备考—汉字与运算

汉字 英文字符 英文字符的编码有两种:①ASCII标准码,7位(128个字符)②ASCII扩展吗,8位(256个字符) 中文字符 汉字分为两级:①一级汉字:3755个,按汉语拼音字母的次序排列。②二级汉字:3008个,按偏旁部首排列。 那么,怎么编码呢?要使用区位码和字形码等等。 区…

Docker环境搭建和监控备份

1. 解释Docker中的容器和镜像的概念&#xff0c;并说明它们在环境搭建中的作用。 Docker中的容器和镜像是Docker最核心的概念&#xff0c;它们在环境搭建中扮演着至关重要的角色。 容器&#xff08;Container&#xff09;&#xff1a; 容器是Docker环境中用于运行应用的实体…

注意力机制网络

注意力机制在深度学习领域中是一种重要的技术&#xff0c;特别是在序列模型和自然语言处理&#xff08;NLP&#xff09;任务中。注意力机制的核心思想是在模型的输入上模拟人类的注意力过程&#xff0c;即模型能够自动决定在处理特定任务时应该“关注”输入数据的哪些部分。通过…

【UE5】游戏框架GamePlay

项目资源文末百度网盘自取 游戏框架 游戏 由 游戏模式(GameMode) 和 游戏状态(GameState) 所组成 加入游戏的 人类玩家 与 玩家控制器(PlayerController) 相关联 玩家控制器允许玩家在游戏中拥有 HUD&#xff0c;这样他们就能在关卡中拥有物理代表 玩家控制器还向玩家提供 …

在centos7系统中如何给docker配置代理

一、需求场景 生产环境私有云中&#xff0c;通常一个集群的机器中只有几台机器可以直接访问公网&#xff0c;其他机器需要通过代理的方式从能访问公网的机器出去&#xff0c;在已经做了如下配置之后&#xff0c;使用docker pull命令已经报错超时timeout&#xff0c;这时可以尝…

利用tree命令自动保存文件层级结构

tree命令的使用 为了将上图左侧的文件目录&#xff0c;生成上图右侧中的文件夹结构列表&#xff0c;保存在txt中&#xff0c;使用了如下cmd命令&#xff1a; C:\armadillo-12.8.0>tree .>list.txt以上tree命令分为3部分&#xff1a; tree 命令. 在当前目录>list.tx…

使用Numpy手工模拟梯度下降算法

代码 import numpy as np # Compute every step manually# Linear regression # f w * x # here : f 2 * x X np.array([1, 2, 3, 4], dtypenp.float32) Y np.array([2, 4, 6, 8], dtypenp.float32)w 0.0# model output def forward(x):return w * x# loss MSE def loss…

02hadoop伪分布式搭建

3. 环境安装 3.1 安装方式 单机模式 只能启动MapReduce 伪分布式 能启动HDFS、MapReduce 和 YARN的大部分功能 完全分布式 能启动Hadoop的所有功能 3.2 安装JDK 3.2.1 JDK安装步骤 下载JDK安装包&#xff08;下载Linux系统的 .tar.gz 的安装包&#xff09; https://www…

循序渐进丨MogDB 数据库特性之动态数据脱敏机制

数据脱敏是行之有效的数据库隐私保护方案之一&#xff0c;可以在一定程度上限制非授权用户对隐私数据的窥探。动态数据脱敏机制是一种通过定制化脱敏策略来实现对隐私数据保护的技术&#xff0c;可以在保留原始数据的前提下有效地解决非授权用户对敏感信息访问的问题。当管理员…

稀碎从零算法笔记Day10-LeecCode:赎金信

题型&#xff1a;哈希表、字符串 链接&#xff1a;383. 赎金信 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以…

Cloud-Sleuth分布式链路追踪(服务跟踪)

简介 在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的服务节点调用来协同产生最后的请求结果,每一个前端请求都会形成一条复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起整个请求最后的失败 GitHub - spring-cloud/spring-cloud-sl…

PostgreSQL常用命令汇总

1 连接数据库&#xff1a;psql -U postgres &#xff08;psql -U username -d databse_name -h host -W&#xff09; -U 指定用户 -d 指定数据库 -h 要链接的主机 -W 提示输入密码 操作说明命令1、切换数据库\c dbname2、列举数据库\l4、列举表\dt5、查看表结构\d tblname6、…

文案高手不能说的秘密,拿来就用的文案素材库

一、素材描述 本套文案素材&#xff0c;大小58.20M&#xff0c;共有43个文件。 二、素材目录 &#xff08;一&#xff09;、一阶文案库 01.1-文案写作行业&#xff1a;年入百万文案高手的赚钱朋友圈&#xff01;.pdf 02.2-个人品牌创业&#xff1a;全网顶流个人品牌大咖都…

什么是仿射变换?

什么是仿射变换&#xff1f; 仿射变换可以理解为对坐标进行缩放、旋转、平移后取得的新坐标的值&#xff0c;也可以理解为经过对坐标的缩放、旋转、平移后原坐标在新坐标系中的值&#xff0c;可以用以下函数来描述 f ( x ) A x b f(x)Axb f(x)Axb 其中&#xff0c;A是变形矩…

WPF(1)的MVVM的数据驱动学习示例

MVVM Model:数据模型、View 界面、ViewModel 业务逻辑处理 项目结构 界面数据绑定 <Window x:Class"WpfApp1.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/x…

vue3注册全局组件

注册单个全局组件 一.在main.ts中引入注册为全局组件 在main.ts 引入我们的组件跟随在createApp(App) 后面 切记不能放到mount 后面这是一个链式调用用其次调用 component 第一个参数组件名称 第二个参数组件实例 import { createApp } from vue import App from ./App.vue …

自然语言发展历程

一、基础知识 自然语言处理&#xff1a;能够让计算理解人类的语言。 检测计算机是否智能化的方法&#xff1a;图灵测试 自然语言处理相关基础点&#xff1a; 基础点1——词表示问题&#xff1a; 1、词表示&#xff1a;把自然语言中最基本的语言单位——词&#xff0c;将它转…

【H5C3】提高课程笔记

一.HTML5新特性 1.语义化标签 &#xff08;★★&#xff09; 以前布局&#xff0c;我们基本用 div 来做。div 对于搜索引擎来说&#xff0c;是没有语义的 <div class“header”> </div> <div class“nav”> </div> <div class“content”> &l…

python:布伊山德U检验(Buishand U test,BUT)突变点检测(以NDVI时间序列为例)

作者:CSDN @ _养乐多_ 本文将介绍布伊山德U检验(Buishand U test,BUT)突变点检测代码。以 NDVI 时间序列为例。输入数据可以是csv,一列NDVI值,一列时间。代码可以扩展到遥感时间序列突变检测(突变年份、突变幅度等)中。 结果如下图所示, 文章目录 一、准备数据二、…

基于Token的身份验证:安全与效率的结合

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…