使用spring cloud 26、spring securiry56、oauth2、spring cloud gateway实现基于ouath2 jwt的统一认证网关
实现这个功能需要进行以下步骤:
-
创建认证中心:使用spring security和oauth2创建一个认证中心,用于管理用户的认证和授权信息。可以使用Spring Security OAuth2的授权服务器来实现。
-
创建资源服务器:创建一个或多个资源服务器,用于提供业务服务。可以使用Spring Security OAuth2的资源服务器来实现。
-
配置JWT:使用JWT作为认证中心和资源服务器之间的认证方式,可以使用Spring Security OAuth2的JWT支持来实现。
-
配置网关:使用Spring Cloud Gateway作为网关,实现请求的路由和统一认证。可以使用Spring Cloud Gateway的过滤器来完成认证和授权的操作。
下面是具体的实现步骤:
- 创建认证中心
创建一个Spring Boot项目,并添加Spring Security OAuth2和JWT的依赖。
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
配置认证中心的授权服务器:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
private TokenStore tokenStore;
@Value("${security.oauth2.client.client-id}")
private String clientId;
@Value("${security.oauth2.client.client-secret}")
private String clientSecret;
@Value("${security.oauth2.client.access-token-validity-seconds}")
private int accessTokenValiditySeconds;
@Value("${security.oauth2.client.refresh-token-validity-seconds}")
private int refreshTokenValiditySeconds;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient(clientId)
.secret(clientSecret)
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write")
.accessTokenValiditySeconds(accessTokenValiditySeconds)
.refreshTokenValiditySeconds(refreshTokenValiditySeconds);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.accessTokenConverter(jwtAccessTokenConverter)
.tokenStore(tokenStore)
.userDetailsService(userDetailsService);
}
}
配置JWT:
@Configuration
public class JwtConfig {
@Value("${jwt.secret}")
private String secret;
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(secret);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
}
- 创建资源服务器
创建一个Spring Boot项目,并添加Spring Security OAuth2和JWT的依赖。
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
配置资源服务器:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("api").tokenStore(tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll();
}
}
配置JWT:
@Configuration
public class JwtConfig {
@Value("${jwt.secret}")
private String secret;
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(secret);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
}
- 配置网关
创建一个Spring Boot项目,并添加Spring Cloud Gateway的依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.0.3</version>
</dependency>
配置网关:
@Configuration
public class GatewayConfig {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("resource", r -> r.path("/api/**")
.filters(f -> f.filter(jwtAuthenticationFilter))
.uri("http://localhost:8081"))
.build();
}
}
配置JWT过滤器:
@Component
public class JwtAuthenticationFilter implements GatewayFilter, Ordered {
@Value("${jwt.secret}")
private String secret;
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String BEARER_PREFIX = "Bearer ";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String authorizationHeader = exchange.getRequest().getHeaders().getFirst(AUTHORIZATION_HEADER);
if (authorizationHeader != null && authorizationHeader.startsWith(BEARER_PREFIX)) {
String jwt = authorizationHeader.substring(BEARER_PREFIX.length());
try {
Jws<Claims> claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(jwt);
String username = claims.getBody().getSubject();
List<String> roles = (List<String>) claims.getBody().get("roles");
Authentication authentication = new UsernamePasswordAuthenticationToken(username, null,
roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (JwtException e) {
return Mono.error(new UnauthorizedException("Invalid token"));
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return SecurityWebFiltersOrder.AUTHENTICATION.getOrder() - 1;
}
}
这样就完成了基于ouath2 jwt的统一认证网关的实现。当用户访问资源服务器时,网关会将用户的请求转发到资源服务器,并在转发前对用户进行认证和授权。
原文地址: https://www.cveoy.top/t/topic/b0Cp 著作权归作者所有。请勿转载和采集!