SpringCloud之SSO单点登录:基于Gateway和OAuth2的跨系统统一认证和鉴权详解

在现代微服务架构中,单点登录(SSO)是一个重要的认证机制。它允许用户在多个服务之间共享登录状态,而不必在每个服务中都进行单独的身份验证。本文将详细介绍如何使用SpringCloud Gateway和OAuth2实现跨系统的统一认证和鉴权。

一、系统架构

本示例架构主要包含三个部分:

  1. 用户认证中心(Authorization Server):处理用户登录,并生成访问令牌。
  2. 资源服务器(Resource Server):提供保护资源,验证访问令牌的有效性。
  3. 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有帮助!

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部