SpringCloud Gateway 權限認證的實現(xiàn)
在微服務架構中,Spring Cloud Gateway 作為網(wǎng)關層,承擔著請求轉發(fā)、權限校驗等重要職責。通過集成 Spring Security 和 JWT(JSON Web Token),可以在網(wǎng)關層實現(xiàn)集中式的權限認證,確保系統(tǒng)的安全性和數(shù)據(jù)保護。以下是詳細的實現(xiàn)步驟:
一、添加依賴
在 Spring Boot 項目中,添加 Spring Cloud Gateway、Spring Security 和 JWT 相關依賴。以下是 pom.xml 的配置示例:
<dependencies>
<!-- Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT Support -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
二、配置 Spring Security
在 Spring Cloud Gateway 中,使用 Spring Security 的 WebFlux 模塊來實現(xiàn)權限校驗。以下是一個典型的配置類:
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http, JwtAuthenticationManager jwtAuthenticationManager) {
http
.csrf().disable() // 禁用 CSRF 保護
.authorizeExchange(exchanges -> exchanges
.pathMatchers("/login", "/register").permitAll() // 公開登錄和注冊接口
.anyExchange().authenticated()) // 其他請求需要認證
.addFilterAt(jwtAuthenticationFilter(jwtAuthenticationManager), SecurityWebFilterChain.class);
return http.build();
}
private AuthenticationWebFilter jwtAuthenticationFilter(JwtAuthenticationManager jwtAuthenticationManager) {
AuthenticationWebFilter filter = new AuthenticationWebFilter(jwtAuthenticationManager);
filter.setServerAuthenticationConverter(new BearerTokenServerAuthenticationConverter());
return filter;
}
}
三、實現(xiàn) JWT 工具類
JWT 工具類用于生成和解析 JWT 令牌。以下是工具類的實現(xiàn):
@Component
public class JwtUtil {
private String secret = "yourSecretKey"; // 密鑰應存儲在安全的地方,避免硬編碼
public Mono<String> extractUsername(String token) {
return Mono.just(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();
}
public Mono<String> generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return Mono.just(createToken(claims, userDetails.getUsername()));
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10小時過期
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
public Mono<Boolean> validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token).block();
return Mono.just(username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
private Boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
}
四、實現(xiàn) JWT 認證管理器
JWT 認證管理器用于處理 JWT 的驗證邏輯:
@Component
public class JwtAuthenticationManager implements ReactiveAuthenticationManager {
private final JwtUtil jwtUtil;
private final UserDetailsService userDetailsService;
public JwtAuthenticationManager(JwtUtil jwtUtil, UserDetailsService userDetailsService) {
this.jwtUtil = jwtUtil;
this.userDetailsService = userDetailsService;
}
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
String token = (String) authentication.getCredentials();
return jwtUtil.extractUsername(token)
.flatMap(username -> {
if (jwtUtil.validateToken(token, userDetailsService.loadUserByUsername(username)).block()) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
return Mono.just(new UsernamePasswordAuthenticationToken(userDetails, token, userDetails.getAuthorities()));
} else {
return Mono.empty();
}
});
}
}
五、實現(xiàn) Bearer Token 轉換器
Bearer Token 轉換器用于從請求頭中提取 JWT 令牌:
public class BearerTokenServerAuthenticationConverter implements ServerAuthenticationConverter {
@Override
public Mono<Authentication> convert(ServerWebExchange exchange) {
String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
return Mono.just(new BearerTokenAuthentication(token));
}
return Mono.empty();
}
}
六、配置 Gateway 路由
在 application.yml 文件中配置路由規(guī)則:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/users/**
filters:
- JwtAuthenticationFilter
七、總結
到此這篇關于SpringCloud Gateway 權限認證的實現(xiàn)的文章就介紹到這了,更多相關SpringCloud Gateway 權限認證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mybatis-plus QueryWrapper中or,and的使用及說明
使用MyBatis Plus QueryWrapper時,因同時添加角色權限固定條件和多字段模糊查詢導致數(shù)據(jù)異常展示,排查發(fā)現(xiàn)OR邏輯覆蓋了權限條件,通過正確使用and()方法,將條件組合為AND邏輯,解決了權限過濾失效的問題2025-07-07
Java 輕松實現(xiàn)二維數(shù)組與稀疏數(shù)組互轉
在某些應用場景中需要大量的二維數(shù)組來進行數(shù)據(jù)存儲,但是二維數(shù)組中卻有著大量的無用的位置占據(jù)著內(nèi)存空間,稀疏數(shù)組就是為了優(yōu)化二維數(shù)組,節(jié)省內(nèi)存空間2022-04-04
聊聊Java 成員變量賦值和構造方法誰先執(zhí)行的問題
這篇文章主要介紹了聊聊Java 成員變量賦值和構造方法誰先執(zhí)行的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10
Quarkus篇入門創(chuàng)建項目搭建debug環(huán)境
這篇文章主要為大家介紹了Quarkus篇入門創(chuàng)建項目搭建debug環(huán)境,先來一套hello?world,來搭建基本的運行及調(diào)試環(huán)境吧2022-02-02
SpringCloud?OpenFeign?服務調(diào)用傳遞?token的場景分析
這篇文章主要介紹了SpringCloud?OpenFeign?服務調(diào)用傳遞?token的場景分析,本篇文章簡單介紹?OpenFeign?調(diào)用傳遞?header?,以及多線程環(huán)境下可能會出現(xiàn)的問題,其中涉及到?ThreadLocal?的相關知識,需要的朋友可以參考下2022-07-07

