SpringCloud之SSO单点登录:基于Gateway和OAuth2的跨系统统一认证和鉴权详解
在现代微服务架构中,单点登录(SSO)是一个重要的认证机制。它允许用户在多个服务之间共享登录状态,而不必在每个服务中都进行单独的身份验证。本文将详细介绍如何使用SpringCloud Gateway和OAuth2实现跨系统的统一认证和鉴权。
一、系统架构
本示例架构主要包含三个部分:
- 用户认证中心(Authorization Server):处理用户登录,并生成访问令牌。
- 资源服务器(Resource Server):提供保护资源,验证访问令牌的有效性。
- API网关(Gateway):统一接入点,转发请求,同时负责OAuth2的身份验证。
二、用户认证中心(Authorization Server)
首先,我们需要构建一个用户认证中心。以下是一个基本的OAuth2授权服务器配置示例:
@EnableAuthorizationServer
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client_id")
.secret("{noop}client_secret") // NoOpPasswordEncoder
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("read", "write")
.autoApprove(true);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
}
以上代码使用内存存储了一些客户端信息,实际应用中可以考虑将数据存储在数据库中。
三、资源服务器(Resource Server)
接下来,配置一个资源服务器,保护特定的API资源。以下是资源服务器的基本配置:
@EnableResourceServer
@Configuration
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("resource_id").stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated();
}
}
在这个配置中,我们将/public/**
路径开放,其他路径都必须经过认证才能访问。
四、API网关(Gateway)
使用SpringCloud Gateway作为统一的入口,首先需要在application.yml
中配置Gateway:
spring:
cloud:
gateway:
routes:
- id: auth-service
uri: http://localhost:8081
predicates:
- Path=/auth/**
- id: resource-service
uri: http://localhost:8082
predicates:
- Path=/api/**
在API网关中,我们可以通过配置OAuth2来确保请求被正确认证。可以通过过滤器对请求的访问令牌进行验证:
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("auth_route", r -> r.path("/auth/**")
.uri("http://localhost:8081"))
.route("resource_route", r -> r.path("/api/**")
.filters(f -> f.filter(new MyAuthenticationFilter()))
.uri("http://localhost:8082"))
.build();
}
}
我们还可以实现一个自定义的过滤器MyAuthenticationFilter
,用于验证访问令牌:
public class MyAuthenticationFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
// 验证token的逻辑
if (isValidToken(token)) {
return chain.filter(exchange);
} else {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
}
private boolean isValidToken(String token) {
// 调用认证中心的接口来验证token
return true; // 这里简单返回true,实际需要调用认证服务
}
}
五、总结
通过以上步骤,我们实现了基于SpringCloud Gateway和OAuth2的单点登录系统。用户只需在认证中心登录一次,就可以在跨系统服务中保持登录状态。使用SpringCloud的微服务架构,结合OAuth2认证机制,可以有效提高应用的安全性与用户体验。构建复杂应用时,可以考虑更细化的权限管理和更多的安全策略。
希望这篇文章对您理解和实现SSO有帮助!