在微服务架构中,spring cloud gateway 作为网关层,承担着请求转发、权限校验等重要职责。通过集成 spring security 和 jwt(json web token),可以在网关层实现集中式的权限认证,确保系统的安全性和数据保护。以下是详细的实现步骤:
一、添加依赖
在 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 模块来实现权限校验。以下是一个典型的配置类:
@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;
}
}
三、实现 jwt 工具类
jwt 工具类用于生成和解析 jwt 令牌。以下是工具类的实现:
@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());
}
}
四、实现 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();
}
});
}
}
五、实现 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 文件中配置路由规则:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- path=/users/**
filters:
- jwtauthenticationfilter
七、总结
到此这篇关于springcloud gateway 权限认证的实现的文章就介绍到这了,更多相关springcloud gateway 权限认证内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论