深圳网站设计哪家公司好,郑州seo优化公司,西安做网站需要多少钱,排版设计英文文章目录 7.1 保护 REST API7.1.1 基础知识详解7.1.2 重点案例#xff1a;使用 JWT 进行身份验证和授权案例 Demo 7.1.3 拓展案例 1#xff1a;API 密钥认证案例 Demo测试API密钥认证 7.1.4 拓展案例 2#xff1a;使用 OAuth2 保护 API案例 Demo测试 OAuth2 保护的 API 7.2 … 文章目录 7.1 保护 REST API7.1.1 基础知识详解7.1.2 重点案例使用 JWT 进行身份验证和授权案例 Demo 7.1.3 拓展案例 1API 密钥认证案例 Demo测试API密钥认证 7.1.4 拓展案例 2使用 OAuth2 保护 API案例 Demo测试 OAuth2 保护的 API 7.2 微服务安全最佳实践7.2.1 基础知识详解7.2.2 重点案例使用 JWT 实现服务间认证案例 Demo 7.2.3 拓展案例 1使用 Spring Cloud Security 简化安全配置案例 Demo 7.2.4 拓展案例 2API 网关安全案例 Demo 7.3 API 网关集成7.3.1 基础知识详解7.3.2 重点案例集成 Spring Cloud Gateway案例 Demo 7.3.3 拓展案例 1限流策略案例 Demo 7.3.4 拓展案例 2使用 JWT 进行身份验证案例 Demo 7.1 保护 REST API
在数字化时代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请求和响应防止数据在传输过程中被截获或篡改。HSTSHTTP Strict Transport Security强制客户端如浏览器使用HTTPS与服务器建立连接。
数据保护
数据加密对敏感数据进行加密处理保护存储在服务器上或传输过程中的数据。数据脱敏在公开的响应中避免直接展示敏感数据如用户ID、电子邮件地址等。
输入验证
目的防止恶意输入导致的安全漏洞如SQL注入、XSS攻击。实践对所有输入数据进行验证拒绝不符合预期格式的请求。
错误处理
优雅处理错误信息应足够通用避免泄露敏感信息或系统细节。日志记录记录错误日志但避免在日志中记录敏感信息。
限制与节流 (Rate Limiting and Throttling)
目的防止API滥用保护后端服务不受恶意攻击或过载。实现限制来自单一来源的请求频率当达到限制时返回适当的HTTP状态码。
通过这些基础知识的详解我们可以看到保护REST API涉及到多个方面包括但不限于身份验证、授权、传输安全、数据保护和输入验证等。正确实施这些安全措施可以有效提高API的安全性保护用户数据和服务的稳定性。
7.1.2 重点案例使用 JWT 进行身份验证和授权
JSON Web TokenJWT是一种开放标准RFC 7519用于在双方之间安全地传输信息作为 JSON 对象。由于其紧凑和自包含的特性JWT 非常适合用于 REST API 的身份验证和授权。以下案例将引导你实现 JWT 在 Spring Boot 应用中的身份验证和授权。
案例 Demo
步骤 1: 引入 JWT 库依赖
首先在 Spring Boot 项目的pom.xml中添加对 JWT 库的依赖。这里我们使用jjwt库作为示例
dependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt/artifactIdversion0.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;Component
public 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, FunctionClaims, 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 {Autowiredprivate MyUserDetailsService userDetailsService;Autowiredprivate JwtUtil jwtUtil;Overrideprotected 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;EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {Autowiredprivate JwtRequestFilter jwtRequestFilter;Overrideprotected 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 拓展案例 1API 密钥认证
API 密钥认证是一种简单但有效的安全措施用于控制对 REST API 的访问。它适用于服务到服务的通信其中一个服务需要验证另一个服务的请求。以下案例演示了如何在 Spring Boot 应用中实现 API 密钥认证。
案例 Demo
步骤 1: 定义 API 密钥存储
首先假设我们有一个简单的方式来存储和验证 API 密钥。在实际应用中这些密钥可能会存储在数据库或配置文件中。这里我们使用一个简单的 Map 模拟。
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;Component
public class ApiKeyStore {private final MapString, 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 {Autowiredprivate ApiKeyStore apiKeyStore;Overrideprotected 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;EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {Beanpublic ApiKeyAuthenticationFilter apiKeyAuthenticationFilter() {return new ApiKeyAuthenticationFilter();}Overrideprotected void configure(HttpSecurity http) throws Exception {http.addFilterBefore(apiKeyAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class).authorizeRequests().anyRequest().authenticated().and().csrf().disable();}
}通过以上步骤Spring Boot 应用现在能够使用 API 密钥进行简单的身份验证。任何未提供有效 API 密钥的请求都将被拒绝访问。
测试API密钥认证
启动应用并尝试发送请求到受保护的端点确保在请求头中包含有效的Service-Id和API-Key。如果密钥验证失败应收到 HTTP 401 Unauthorized 错误。
这种 API 密钥认证方法虽然简单但在某些场景下非常有效尤其是在服务对服务的通信中。记得保护好你的 API 密钥避免泄露。
7.1.4 拓展案例 2使用 OAuth2 保护 API
OAuth2是一个开放标准允许用户授权第三方应用访问其服务器资源而无需将用户名和密码直接暴露给第三方应用。这种机制特别适合需要跨应用授权的场景。在本案例中我们将展示如何在Spring Boot应用中使用OAuth2保护REST API。
案例 Demo
步骤 1: 引入Spring Security OAuth2依赖
首先确保你的Spring Boot项目中包含了Spring Security OAuth2的依赖。在pom.xml文件中添加
dependencygroupIdorg.springframework.security/groupIdartifactIdspring-security-oauth2/artifactIdversion2.3.6.RELEASE/version
/dependency
dependencygroupIdorg.springframework.security/groupIdartifactIdspring-security-jwt/artifactIdversion1.0.10.RELEASE/version
/dependency步骤 2: 配置授权服务器
创建一个配置类AuthorizationServerConfig来配置OAuth2授权服务器。这里我们使用内存中的客户端和用户存储作为示例。
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;Configuration
EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient(client-id).secret({noop}client-secret).authorizedGrantTypes(authorization_code, refresh_token, password).scopes(read, write).autoApprove(true);}
}步骤 3: 配置资源服务器
创建一个配置类ResourceServerConfig来配置OAuth2资源服务器。这里我们定义了一些安全限制以保护API端点。
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;Configuration
EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers(/api/**).authenticated().anyRequest().permitAll();}
}步骤 4: 定义用户详情服务
为了支持password授权类型你需要定义一个UserDetailsService。在这个例子中我们简单地在内存中创建一个用户。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;Configuration
public class UserDetailsConfig {Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager manager new InMemoryUserDetailsManager();manager.createUser(User.withUsername(user).password({noop}password).roles(USER).build());return manager;}
}测试 OAuth2 保护的 API
启动应用后首先获取访问令牌
对于password授权类型可以使用HTTP请求直接向授权服务器发送用户名和密码来获取令牌。对于authorization_code类型需要通过用户代理如Web浏览器重定向到授权服务器的登录页面用户登录后授权服务器会将令牌重定向回客户端指定的重定向URI。
一旦获取到访问令牌就可以在请求的Authorization头中使用它来访问受保护的资源。
通过以上步骤你的Spring Boot应用现在能够利用OAuth2进行身份验证和授权从而保护REST API免受未经授权的访问。这种方法为应用提供了强大的安全性和灵活性使其能够安全地与外部应用或服务进行交互。
通过实现这些策略和案例你可以有效地保护你的 REST API 免受常见安全威胁确保数据的安全和服务的可用性。记住安全是一个持续的过程需要定期审查和更新你的安全策略和实践。
7.2 微服务安全最佳实践
微服务架构通过将应用拆分为一系列较小、独立的服务来提高灵活性和可维护性。然而这种分散的架构也带来了新的安全挑战。保护微服务不仅要求保证数据的安全还要确保服务间通信的安全。以下是微服务安全的一些基础知识和最佳实践。
7.2.1 基础知识详解
在微服务架构中应用被拆分成多个服务每个服务执行特定的功能并通过网络进行通信。这种架构提高了应用的可伸缩性和灵活性但同时也引入了新的安全挑战。下面详细探讨微服务安全的关键方面和最佳实践。
服务间通信安全
TLS/SSL加密所有服务间的通信都应通过TLS传输层安全协议进行加密确保数据传输过程中的机密性和完整性。双向SSL在某些情况下服务之间还需要相互验证对方的身份这可以通过双向SSL又称为客户端证书认证来实现。
身份验证和授权
统一身份认证机制微服务架构应该有一个集中的身份认证服务所有服务都应通过这个服务来认证用户身份。细粒度授权授权决策应基于用户的角色或权限以及服务的安全策略。可以实现角色基础访问控制RBAC或更灵活的属性基访问控制ABAC。
API 网关
集中安全控制API网关作为微服务架构中的统一入口可以在这里集中实施身份验证、授权、流量限制等安全策略。流量管理API网关可以对流量进行监控和控制实现请求限流和熔断防止服务被过度使用或恶意攻击。
安全令牌服务
OAuth2和JWTOAuth2是一个授权框架允许第三方应用代表用户访问其资源而JWTJSON Web Token通常用于在OAuth2流程中携带身份验证和授权信息。
微服务防御措施
输入验证所有服务都应实施严格的输入验证以防止SQL注入、跨站脚本XSS等攻击。依赖管理定期更新服务的依赖库修补已知的安全漏洞。错误处理适当的错误处理可以防止敏感信息泄露应避免在响应中返回过多的错误细节。
安全编码实践
代码审计和扫描定期进行代码审计和使用自动化工具扫描代码以发现潜在的安全问题。敏感数据保护对敏感数据进行加密处理并在存储和传输时采取适当的保护措施。
通过理解和实施这些基础知识和最佳实践你可以为微服务架构构建坚实的安全基础保护你的应用免受各种网络安全威胁。安全是一个持续的过程需要不断地审视、更新和改进安全策略和措施。
7.2.2 重点案例使用 JWT 实现服务间认证
在微服务架构中服务间认证是确保每个服务的请求都来自受信任来源的重要机制。使用JSON Web TokensJWT进行服务间认证不仅能提供安全保障还能确保认证过程的轻量和高效。以下案例演示了如何在Spring Boot微服务架构中实现JWT进行服务间认证。
案例 Demo
步骤 1: 创建JWT工具类
首先创建一个JwtTokenUtil类来处理JWT的生成和验证。这个类将提供生成JWT的方法和验证JWT的方法。
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.function.Function;Component
public class JwtTokenUtil {Value(${jwt.secret})private String secret;Value(${jwt.expiration})private Long expiration;public String generateToken(String subject) {return Jwts.builder().setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() expiration)).signWith(SignatureAlgorithm.HS512, secret).compact();}public Boolean validateToken(String token, String subject) {final String tokenSubject getClaimFromToken(token, Claims::getSubject);return (subject.equals(tokenSubject) !isTokenExpired(token));}public T T getClaimFromToken(String token, FunctionClaims, T claimsResolver) {final Claims claims getAllClaimsFromToken(token);return claimsResolver.apply(claims);}private Claims getAllClaimsFromToken(String token) {return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();}private Boolean isTokenExpired(String token) {final Date expiration getClaimFromToken(token, Claims::getExpiration);return expiration.before(new Date());}
}在application.properties中配置JWT密钥和过期时间
jwt.secretYourSecretKey
jwt.expiration604800000 # JWT token的过期时间这里设置为7天步骤 2: 实现服务间请求拦截器
创建一个FeignClientInterceptor拦截器用于在发送服务间请求时附加JWT。
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;Component
public class FeignClientInterceptor implements RequestInterceptor {Autowiredprivate JwtTokenUtil jwtTokenUtil;Overridepublic void apply(RequestTemplate template) {template.header(Authorization, Bearer jwtTokenUtil.generateToken(service-account));}
}步骤 3: 配置服务接收方验证JWT
在服务接收方创建一个JwtRequestFilter过滤器来验证每个进入的请求的JWT。
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 JwtRequestFilter extends OncePerRequestFilter {Autowiredprivate JwtTokenUtil jwtTokenUtil;Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException {final String requestTokenHeader request.getHeader(Authorization);String jwtToken null;if (requestTokenHeader ! null requestTokenHeader.startsWith(Bearer )) {jwtToken requestTokenHeader.substring(7);try {if (!jwtTokenUtil.validateToken(jwtToken, service-account)) {throw new ServletException(JWT Token is invalid);}} catch (Exception e) {throw new ServletException(JWT Token validation failed, e);}} else {logger.warn(JWT Token does not begin with Bearer String);}chain.doFilter(request, response);}
}步骤 4: 在服务接收方配置Spring Security使用JWT过滤器
最后在服务接收方的Spring Security配置中注册JwtRequestFilter来验证进入的请求。
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;EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {Beanpublic JwtRequestFilter jwtRequestFilter() {return new JwtRequestFilter();}Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().addFilterBefore(jwtRequestFilter(), UsernamePasswordAuthenticationFilter.class).authorizeRequests().anyRequest().authenticated();}
}通过上述步骤微服务架构中的服务间通信将通过JWT进行安全认证确保只有验证通过的服务请求才能被接受和处理。这种方法为服务间通信提供了一个安全的认证机制有助于防止未授权访问。
7.2.3 拓展案例 1使用 Spring Cloud Security 简化安全配置
Spring Cloud Security 提供了一套简化微服务安全配置的工具使得实现复杂的安全需求变得更加直接和简单。利用 Spring Cloud Security可以轻松实现服务间的安全通信、统一的身份验证和授权等功能。以下案例将展示如何使用 Spring Cloud Security 在微服务架构中简化安全配置。
案例 Demo
假设我们有一个微服务架构需要在服务间实现基于 OAuth2 的安全通信。以下是步骤和示例代码
步骤 1: 引入 Spring Cloud Security 依赖
首先在微服务项目的pom.xml文件中添加 Spring Cloud Security 依赖
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-security/artifactId
/dependency
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-oauth2/artifactId
/dependency步骤 2: 配置资源服务器
在微服务中配置资源服务器以使用 OAuth2 令牌进行安全验证。创建一个配置类ResourceServerConfig 继承 ResourceServerConfigurerAdapter并使用 EnableResourceServer 注解来启用资源服务器。
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers(/public/**).permitAll() // 公开访问的端点.anyRequest().authenticated(); // 其他所有请求都需要验证}
}步骤 3: 配置OAuth2客户端
如果服务需要作为客户端访问其他受保护的服务可以在application.yml或application.properties中配置OAuth2客户端详细信息
security:oauth2:client:clientId: myClientIdclientSecret: myClientSecretaccessTokenUri: http://AUTH-SERVER/oauth/tokenuserAuthorizationUri: http://AUTH-SERVER/oauth/authorizeresource:userInfoUri: http://AUTH-SERVER/userinfo步骤 4: 使用 Feign 客户端进行服务间调用
当使用 Feign 客户端进行服务间调用时可以通过配置自动携带 OAuth2 令牌。首先确保 Feign 客户端在请求时携带 OAuth2 令牌
import feign.RequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;public class FeignClientConfig {Beanpublic RequestInterceptor oauth2FeignRequestInterceptor(OAuth2RestTemplate oAuth2RestTemplate) {return requestTemplate - {requestTemplate.header(Authorization, Bearer oAuth2RestTemplate.getAccessToken().getValue());};}
}在 Feign 客户端接口上应用配置
FeignClient(name other-service, configuration FeignClientConfig.class)
public interface OtherServiceClient {// 定义访问其他服务的方法
}通过上述步骤你可以利用 Spring Cloud Security 简化微服务架构中的安全配置无需编写大量的安全配置代码就可以实现服务间的安全通信和访问控制。这种方法不仅减轻了开发负担还提高了安全性和可维护性。
7.2.4 拓展案例 2API 网关安全
在微服务架构中API网关扮演着重要的角色它不仅是微服务的统一入口也是实施安全策略的理想位置。通过在API网关层面集中处理身份验证、授权、以及流量控制可以大大简化单个微服务的安全配置。以下案例将演示如何利用Spring Cloud Gateway实现API网关的安全配置。
案例 Demo
步骤 1: 引入Spring Cloud Gateway依赖
首先确保在微服务项目的pom.xml中引入Spring Cloud Gateway依赖
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId
/dependency步骤 2: 配置API网关路由
接下来在application.yml中配置API网关的路由规则将不同的请求转发到对应的微服务
spring:cloud:gateway:routes:- id: user-serviceuri: lb://USER-SERVICEpredicates:- Path/user/**filters:- RemoveRequestHeaderCookie- id: order-serviceuri: lb://ORDER-SERVICEpredicates:- Path/order/**这里使用了lb://前缀指定服务发现中的服务IDRemoveRequestHeader过滤器用来移除敏感的请求头信息。
步骤 3: 实现全局过滤器进行身份验证
在API网关中实现一个全局过滤器用于检查请求是否包含有效的身份验证信息如JWT令牌。创建GlobalAuthFilter类实现GlobalFilter接口
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;Component
public class GlobalAuthFilter implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 检查请求中的身份验证信息例如JWT令牌String token exchange.getRequest().getHeaders().getFirst(Authorization);if (token null || !token.startsWith(Bearer )) {exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}// 进行令牌验证...return chain.filter(exchange);}Overridepublic int getOrder() {return -100; // 设置过滤器优先级}
}步骤 4: 限流和熔断配置
使用Spring Cloud Gateway的内置支持来配置限流和熔断保护后端微服务不受恶意访问或流量洪峰的影响。在application.yml中添加相应配置
spring:cloud:gateway:routes:- id: user-serviceuri: lb://USER-SERVICEpredicates:- Path/user/**filters:- name: RequestRateLimiterargs:key-resolver: #{userKeyResolver}redis-rate-limiter.replenishRate: 10redis-rate-limiter.burstCapacity: 20这里配置了一个基于Redis的请求速率限制器key-resolver用于确定限流的键这里假设已经有一个userKeyResolver的Bean定义了用户识别逻辑。
通过这些步骤你的API网关将能够有效地管理和保护微服务架构中的流量实现统一的身份验证、授权以及流量控制。通过在API网关集中处理安全逻辑可以减轻各个微服务的安全负担简化安全配置和管理。
通过实施这些微服务安全最佳实践你可以构建一个既灵活又安全的微服务架构有效保护服务和数据免受各种网络安全威胁的侵害。记得安全是一个持续的过程需要定期审查和更新你的安全策略和实践。
7.3 API 网关集成
在微服务架构中API网关作为客户端和服务之间的中介承担着路由请求、聚合响应、身份验证与授权、以及流量监控等关键职责。通过集成API网关可以在微服务架构中实现统一的入口点简化客户端的交互同时加强服务的安全性和可管理性。
7.3.1 基础知识详解
在现代微服务架构中API网关不仅仅是一个简单的路由器而是服务和数据流的关键管理点。它承担着请求转发、服务聚合、安全验证、流量控制和监控等多项职责。深入理解API网关的作用和配置方法对于构建一个高效、安全的微服务系统至关重要。
请求路由
定义API网关接收外部请求并根据预定义的规则将请求转发到对应的后端服务。作用实现了请求的负载均衡提高了系统的可用性和扩展性。
服务聚合
定义API网关可以将来自多个微服务的数据聚合成一个统一的响应返回给客户端。优势减少了客户端需要发送的请求数量优化了数据交互流程提高了用户体验。
身份验证与授权
中心化安全策略在API网关层面集中处理所有进入微服务系统的请求的身份验证和授权。优点简化了单个微服务的安全配置提高了安全性和维护性。
流量控制
限流限制对API的请求速率防止服务因过载而崩溃。熔断在下游服务不可用时自动停止向其发送请求防止故障蔓延。
日志和监控
集中式日志管理API网关可以记录所有经过的请求和响应为系统监控和故障排查提供详细数据。监控指标收集关于请求延迟、成功率和服务健康状况等关键指标帮助维护系统稳定性。
安全性
传输加密使用HTTPS等技术加密客户端和API网关之间的通信保护数据安全。跨域资源共享CORSAPI网关可以统一处理CORS预检请求简化后端服务的CORS配置。
通过这些基础知识的了解我们可以看到API网关在微服务架构中发挥着至关重要的作用不仅优化了服务的调用和数据的聚合还大大增强了系统的安全性和可观测性。正确配置和使用API网关对于保障微服务架构的健康运行至关重要。
7.3.2 重点案例集成 Spring Cloud Gateway
Spring Cloud Gateway提供了一个简单而强大的方式来构建API网关它与Spring生态系统无缝集成支持动态路由、过滤和安全性配置。下面的案例将指导你如何在Spring Boot应用中集成Spring Cloud Gateway实现API网关的基本功能。
案例 Demo
步骤 1: 创建Spring Boot项目并引入依赖
首先确保你的pom.xml文件中包含了Spring Cloud Gateway的依赖
dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactIdversionYOUR_SPRING_CLOUD_VERSION/version/dependency
/dependenciesdependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversionYOUR_SPRING_CLOUD_VERSION/versiontypepom/typescopeimport/scope/dependency/dependencies
/dependencyManagement请替换YOUR_SPRING_CLOUD_VERSION为当前Spring Cloud的版本比如Hoxton.SR9。
步骤 2: 配置路由规则
在application.yml文件中配置路由规则将不同的请求路径路由到对应的微服务
spring:cloud:gateway:routes:- id: user-serviceuri: lb://USER-SERVICEpredicates:- Path/user/**filters:- StripPrefix1- id: product-serviceuri: lb://PRODUCT-SERVICEpredicates:- Path/product/**filters:- StripPrefix1这里使用lb://表示使用Spring Cloud的负载均衡StripPrefix1过滤器用于移除请求路径中的第一部分。
步骤 3: 添加全局过滤器进行请求日志记录
创建一个全局过滤器GlobalLoggingFilter来记录每个请求的详细信息
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;Component
public class GlobalLoggingFilter implements GlobalFilter, Ordered {private final Logger logger LoggerFactory.getLogger(GlobalLoggingFilter.class);Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {logger.info(Original request path: {}, exchange.getRequest().getPath());return chain.filter(exchange).then(Mono.fromRunnable(() -logger.info(Response status code: {}, exchange.getResponse().getStatusCode())));}Overridepublic int getOrder() {return -1; // 设置过滤器顺序}
}步骤 4: 配置安全性和跨域可选
如果需要在API网关层面配置安全性和CORS支持
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;Configuration
public class GatewayConfig {Beanpublic CorsWebFilter corsWebFilter() {CorsConfiguration config new CorsConfiguration();config.addAllowedMethod(*);config.addAllowedOrigin(*);config.addAllowedHeader(*);UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(new PathPatternParser());source.registerCorsConfiguration(/**, config);return new CorsWebFilter(source);}
}通过这些步骤你已经成功地在Spring Boot项目中集成了Spring Cloud Gateway配置了路由规则添加了全局日志记录过滤器并可选地配置了安全性和CORS支持。Spring Cloud Gateway作为API网关不仅提高了微服务架构的灵活性和可维护性也加强了整个系统的安全性。
7.3.3 拓展案例 1限流策略
在面对高流量的情况下限流是保护微服务不被过度使用、避免系统崩溃的关键策略。Spring Cloud Gateway提供了内置的限流功能可以通过配置轻松实现。以下案例将展示如何在Spring Cloud Gateway中配置限流策略。
案例 Demo
步骤 1: 引入Redis依赖
首先确保你的项目中包含了Redis的依赖因为Spring Cloud Gateway的限流特性默认是基于Redis实现的。
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis-reactive/artifactId
/dependency步骤 2: 配置限流规则
在application.yml文件中配置限流规则。你可以根据需要定义不同的限流条件如IP地址、用户ID等。以下示例展示了如何基于请求路径和IP地址进行限流
spring:cloud:gateway:routes:- id: user-serviceuri: lb://USER-SERVICEpredicates:- Path/user/**filters:- name: RequestRateLimiterargs:key-resolver: #{ipKeyResolver}redis-rate-limiter.replenishRate: 5redis-rate-limiter.burstCapacity: 10这里的replenishRate表示每秒允许的请求数burstCapacity表示在短时间内允许的最大请求数。
步骤 3: 实现KeyResolver
创建一个Bean来定义如何解析限流的key。在这个例子中我们根据客户端IP地址进行限流
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;Configuration
public class RateLimiterConfig {BeanKeyResolver ipKeyResolver() {return new KeyResolver() {Overridepublic MonoString resolve(ServerWebExchange exchange) {return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());}};}
}步骤 4: 测试限流策略
启动项目并向配置了限流规则的服务发送请求。如果请求速率超过了配置的replenishRate和burstCapacity则会收到HTTP 429 Too Many Requests错误响应。
通过这些步骤你可以在Spring Cloud Gateway中配置灵活的限流策略有效防止服务被过度请求保护系统稳定运行。这种基于Redis的限流机制不仅实现简单而且支持高并发处理非常适合微服务架构中的流量管理需求。
7.3.4 拓展案例 2使用 JWT 进行身份验证
在微服务架构中通过JWTJSON Web Tokens进行身份验证可以有效地管理和验证用户和服务的身份。JWT为服务间的安全通信提供了一种简便的方式。在这个案例中我们将展示如何在Spring Cloud Gateway中集成JWT进行身份验证。
案例 Demo
步骤 1: 引入 JWT 依赖
首先确保你的Spring Boot项目中包含JWT处理库的依赖。这里我们使用jjwt库作为示例
dependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt/artifactIdversion0.9.1/version
/dependency步骤 2: 实现JWT验证过滤器
在API网关中创建一个自定义的全局过滤器用于解析和验证每个请求中的JWT令牌。如果令牌无效则拒绝访问。
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;Component
public class JwtAuthenticationFilter implements GlobalFilter, Ordered {Value(${jwt.secret})private String secretKey;Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {String token exchange.getRequest().getHeaders().getFirst(Authorization);if (token null || !token.startsWith(Bearer )) {exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}try {token token.substring(7); // Remove Bearer prefixClaims claims Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();// Optionally, further verification logic here} catch (SignatureException e) {exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}return chain.filter(exchange);}Overridepublic int getOrder() {return -100;}
}步骤 3: 配置应用密钥
在application.properties或application.yml中配置JWT的密钥
jwt.secretYourSecretKeyHere请确保这个密钥与生成JWT时使用的密钥相匹配。
步骤 4: 测试JWT身份验证
现在当你通过API网关访问微服务时需要在HTTP请求的Header中附加有效的JWT令牌。可以使用Postman或其他HTTP客户端工具来测试这一功能。如果没有提供令牌或令牌无效网关将拒绝访问并返回HTTP状态码401 Unauthorized。
通过上述步骤Spring Cloud Gateway现在能够利用JWT令牌进行身份验证从而为微服务架构中的安全通信提供了一层额外的保护。这种方法不仅保障了API的安全性还提高了系统的可扩展性和维护性。