阿里云开发者社区

电脑版
提示:原网页已由神马搜索转码, 内容由developer.aliyun.com提供.

第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)(上)

2024-04-19258
版权
版权声明:
本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议》和 《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
简介:第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)

9526b1d6ced59dd11678343f8411959.png

7.1 保护 RESTAPI

在数字化时代,REST API是现代Web应用和微服务架构中数据交互的关键组成部分。然而,随着它们的普及和重要性的增加,保护这些API免受恶意攻击变得尤为重要。本节将探讨保护REST API的基础知识和实用案例。

7.1.1 基础知识详解

在构建和维护REST API时,安全性是一个不容忽视的要素。REST API作为应用程序与外界交互的接口,常常面临着各种安全威胁,包括但不限于身份盗窃、数据泄露、服务拒绝攻击等。因此,采取有效的安全措施保护REST API是至关重要的。以下是保护REST API时需掌握的基础知识。

身份验证 (Authentication)

  • 定义:确定请求者的身份,确保只有合法用户可以访问API。
  • 方法
  • 基本认证:通过HTTP头传递用户名和密码的简单认证方法,需要使用HTTPS来避免凭证泄露。
  • 令牌认证:如JWT,通过签名的令牌确认用户身份,支持无状态认证。
  • OAuth/OAuth2:为第三方应用提供限制的访问权限,而无需暴露用户的凭证。

授权 (Authorization)

  • 定义:确定已认证的用户可以执行的操作或访问的数据。
  • 实现方式
  • 角色基础的访问控制(RBAC):根据用户的角色来决定其权限。
  • 属性基础的访问控制(ABAC):根据属性(用户属性、资源属性和环境属性)来动态决定访问权限。

传输安全 (Transport Security)

  • HTTPS:使用SSL/TLS加密HTTP请求和响应,防止数据在传输过程中被截获或篡改。
  • HSTS(HTTP Strict Transport Security):强制客户端(如浏览器)使用HTTPS与服务器建立连接。

数据保护

  • 数据加密:对敏感数据进行加密处理,保护存储在服务器上或传输过程中的数据。
  • 数据脱敏:在公开的响应中避免直接展示敏感数据,如用户ID、电子邮件地址等。

输入验证

  • 目的:防止恶意输入导致的安全漏洞,如SQL注入、XSS攻击。
  • 实践:对所有输入数据进行验证,拒绝不符合预期格式的请求。

错误处理

  • 优雅处理:错误信息应足够通用,避免泄露敏感信息或系统细节。
  • 日志记录:记录错误日志,但避免在日志中记录敏感信息。

限制与节流 (Rate Limiting and Throttling)

  • 目的:防止API滥用,保护后端服务不受恶意攻击或过载。
  • 实现:限制来自单一来源的请求频率,当达到限制时返回适当的HTTP状态码。

通过这些基础知识的详解,我们可以看到保护REST API涉及到多个方面,包括但不限于身份验证、授权、传输安全、数据保护和输入验证等。正确实施这些安全措施,可以有效提高API的安全性,保护用户数据和服务的稳定性。

7.1.2 重点案例:使用 JWT 进行身份验证和授权

JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在双方之间安全地传输信息作为 JSON 对象。由于其紧凑和自包含的特性,JWT 非常适合用于 REST API 的身份验证和授权。以下案例将引导你实现 JWT 在 Spring Boot 应用中的身份验证和授权。

案例 Demo

步骤 1: 引入 JWT 库依赖

首先,在 Spring Boot 项目的pom.xml中添加对 JWT 库的依赖。这里我们使用jjwt库作为示例:

<dependency>    <groupId>io.jsonwebtoken</groupId>    <artifactId>jjwt</artifactId>    <version>0.9.1</version></dependency>

步骤 2: 创建JWT工具类

创建一个JWT工具类JwtUtil,用于生成和验证 JWT 令牌:

import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import org.springframework.stereotype.Component;import java.util.Date;import java.util.function.Function;@Componentpublic class JwtUtil {    private String secret = "yourSecretKey"; // 用于签名的密钥    public String extractUsername(String token) {        return extractClaim(token, Claims::getSubject);    }    public Date extractExpiration(String token) {        return extractClaim(token, Claims::getExpiration);    }    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {        final Claims claims = extractAllClaims(token);        return claimsResolver.apply(claims);    }    private Claims extractAllClaims(String token) {        return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();    }    private Boolean isTokenExpired(String token) {        return extractExpiration(token).before(new Date());    }    public String generateToken(String username) {        return Jwts.builder().setSubject(username)                .setIssuedAt(new Date(System.currentTimeMillis()))                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10小时有效期                .signWith(SignatureAlgorithm.HS256, secret).compact();    }    public Boolean validateToken(String token, String username) {        final String tokenUsername = extractUsername(token);        return (username.equals(tokenUsername) && !isTokenExpired(token));    }}

步骤 3: 实现 JWT 请求过滤器

创建JwtRequestFilter类,它将在每次请求时检查 JWT 令牌的有效性:

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class JwtRequestFilter extends OncePerRequestFilter {    @Autowired    private MyUserDetailsService userDetailsService;    @Autowired    private JwtUtil jwtUtil;    @Override    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)            throws ServletException, IOException {                final String authorizationHeader = request.getHeader("Authorization");        String username = null;        String jwt = null;        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {            jwt = authorizationHeader.substring(7);            username = jwtUtil.extractUsername(jwt);        }        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);            if (jwtUtil.validateToken(jwt, userDetails.getUsername())) {                UsernamePasswordAuthenticationToken authToken =                         new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());                authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));                SecurityContextHolder.getContext().setAuthentication(authToken);            }        }        chain.doFilter(request, response);    }}

步骤 4: 配置 Spring Security

最后,在 Spring Security 配置中注册JwtRequestFilter

import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.security.config.http.SessionCreationPolicy;import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {    @Autowired    private JwtRequestFilter jwtRequestFilter;    @Override    protected void configure(HttpSecurity http) throws Exception {        http.csrf().disable()                .authorizeRequests().antMatchers("/authenticate").permitAll()                .anyRequest().authenticated()                .and().sessionManagement()                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);    }}

通过这些步骤,你的 Spring Boot 应用现在能够利用 JWT 进行身份验证和授权,从而保护 REST API 免受未授权访问。记得保密你的 JWT 密钥,并定期更新以维护系统安全。

7.1.3 拓展案例 1:API 密钥认证

API 密钥认证是一种简单但有效的安全措施,用于控制对 REST API 的访问。它适用于服务到服务的通信,其中一个服务需要验证另一个服务的请求。以下案例演示了如何在 Spring Boot 应用中实现 API 密钥认证。

案例 Demo

步骤 1: 定义 API 密钥存储

首先,假设我们有一个简单的方式来存储和验证 API 密钥。在实际应用中,这些密钥可能会存储在数据库或配置文件中。这里我们使用一个简单的 Map 模拟。

import org.springframework.stereotype.Component;import java.util.HashMap;import java.util.Map;@Componentpublic class ApiKeyStore {    private final Map<String, String> apiKeys = new HashMap<>();    public ApiKeyStore() {        // 初始化一些API密钥,实际应用中应该从安全的地方加载        apiKeys.put("service1", "key-123");        apiKeys.put("service2", "key-456");    }    public boolean validateKey(String serviceId, String apiKey) {        return apiKey.equals(apiKeys.get(serviceId));    }}

步骤 2: 实现 API 密钥认证过滤器

创建ApiKeyAuthenticationFilter类,该过滤器负责拦截请求并验证 API 密钥。

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class ApiKeyAuthenticationFilter extends OncePerRequestFilter {    @Autowired    private ApiKeyStore apiKeyStore;    @Override    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)            throws ServletException, IOException {                String serviceId = request.getHeader("Service-Id");        String apiKey = request.getHeader("API-Key");        if (serviceId == null || apiKey == null || !apiKeyStore.validateKey(serviceId, apiKey)) {            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid API Key");            return;        }        chain.doFilter(request, response);    }}

步骤 3: 在Spring Security 配置中注册 API 密钥认证过滤器

接下来,需要在 Spring Security 配置中添加ApiKeyAuthenticationFilter

import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.context.annotation.Bean;import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {    @Bean    public ApiKeyAuthenticationFilter apiKeyAuthenticationFilter() {        return new ApiKeyAuthenticationFilter();    }    @Override    protected void configure(HttpSecurity http) throws Exception {        http            .addFilterBefore(apiKeyAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)            .authorizeRequests()                .anyRequest().authenticated()            .and()            .csrf().disable();    }}

通过以上步骤,Spring Boot 应用现在能够使用 API 密钥进行简单的身份验证。任何未提供有效 API 密钥的请求都将被拒绝访问。

测试API密钥认证

启动应用并尝试发送请求到受保护的端点,确保在请求头中包含有效的Service-IdAPI-Key。如果密钥验证失败,应收到 HTTP 401 Unauthorized 错误。

这种 API 密钥认证方法虽然简单,但在某些场景下非常有效,尤其是在服务对服务的通信中。记得保护好你的 API 密钥,避免泄露。


第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)(中)+https://developer.aliyun.com/article/1487156

目录
相关文章
|
3月前
|
Cloud NativeAPI
微服务引擎 MSE 及云原生 API 网关 2025 年 3 月产品动态
微服务引擎 MSE 及云原生 API 网关 2025 年 3 月产品动态
|
4月前
|
Cloud NativeAPI
微服务引擎 MSE 及云原生 API 网关 2025 年 2 月产品动态
微服务引擎 MSE 及云原生 API 网关 2025 年 2 月产品动态
|
18天前
|
缓存负载均衡监控
微服务架构下的电商API接口设计:策略、方法与实战案例
本文探讨了微服务架构下的电商API接口设计,旨在打造高效、灵活与可扩展的电商系统。通过服务拆分(如商品、订单、支付等模块)和标准化设计(RESTful或GraphQL风格),确保接口一致性与易用性。同时,采用缓存策略、负载均衡及限流技术优化性能,并借助Prometheus等工具实现监控与日志管理。微服务架构的优势在于支持敏捷开发、高并发处理和独立部署,满足电商业务快速迭代需求。未来,电商API设计将向智能化与安全化方向发展。
|
2月前
|
API
微服务引擎 MSE 及 API 网关 2025 年 4 月产品动态
微服务引擎 MSE 及 API 网关 2025 年 4 月产品动态
|
1月前
|
运维Cloud Native应用服务中间件
阿里云微服务引擎 MSE 及 API 网关 2025 年 5 月产品动态
阿里云微服务引擎 MSE 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka )、云原生网关(原生支持Higress/Nginx/Envoy,遵循Ingress标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。API 网关 (API Gateway),提供 APl 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 生命周期阶段。帮助您快速构建以 API 为核心的系统架构.满足新技术引入、系统集成、业务中台等诸多场景需要
|
3月前
|
存储人工智能Java
Spring AI与DeepSeek实战四:系统API调用
在AI应用开发中,工具调用是增强大模型能力的核心技术,通过让模型与外部API或工具交互,可实现实时信息检索(如天气查询、新闻获取)、系统操作(如创建任务、发送邮件)等功能;本文结合Spring AI与大模型,演示如何通过Tool Calling实现系统API调用,同时处理多轮对话中的会话记忆。
6705757
|
2月前
|
运维Cloud Native应用服务中间件
阿里云微服务引擎 MSE 及 API 网关 2025 年 4 月产品动态
阿里云微服务引擎 MSE 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka )、云原生网关(原生支持Higress/Nginx/Envoy,遵循Ingress标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。API 网关 (API Gateway),提供 APl 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 生命周期阶段。帮助您快速构建以 API 为核心的系统架构.满足新技术引入、系统集成、业务中台等诸多场景需要
阿里云微服务引擎 MSE 及 API 网关 2025 年 4 月产品动态
|
5月前
|
Cloud NativeAPI微服务
微服务引擎 MSE 及云原生 API 网关 2025 年 1 月产品动态
微服务引擎 MSE 及云原生 API 网关 2025 年 1 月产品动态。
|
3月前
|
运维Cloud Native应用服务中间件
阿里云微服务引擎 MSE 及 云原生 API 网关 2025 年 3 月产品动态
阿里云微服务引擎 MSE 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka )、云原生网关(原生支持Higress/Nginx/Envoy,遵循Ingress标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。API 网关 (API Gateway),提供 APl 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 生命周期阶段。帮助您快速构建以 API 为核心的系统架构.满足新技术引入、系统集成、业务中台等诸多场景需要

热门文章

最新文章