Spring Cloud Security实现微服务间的安全通信示例

2023-04-14 10:04:29 浏览数 (3)

Spring Cloud Security示例

下面是一个使用Spring Cloud Security的示例,该示例包括一个授权服务器和两个客户端,客户端之间通过授权服务器进行安全通信。

(1)授权服务器

授权服务器使用Spring Security OAuth2实现。在pom.xml文件中添加以下依赖:

代码语言:javascript复制
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.4.1</version>
</dependency>

在授权服务器的配置文件中,配置OAuth2的客户端和提供者信息:

代码语言:javascript复制
spring:
  security:
    oauth2:
      client:
        registration:
          my-client-1:
            client-id: my-client-1
            client-secret: my-secret-1
            authorization-grant-type: authorization_code
            redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
            scope:
              - read
              - write
              - trust
          my-client-2:
            client-id: my-client-2
            client-secret: my-secret-2
            authorization-grant-type: authorization_code
            redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
            scope:
              - read
              - write
              - trust
        provider:
          my-provider:
            authorization-uri: https://provider.com/oauth2/authorize
            token-uri: https://provider.com/oauth2/token
            user-info-uri: https://provider.com/oauth2/userinfo
            user-name-attribute: name

然后,创建一个授权服务器配置类,配置OAuth2的授权服务器和令牌存储:

代码语言:javascript复制
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private DataSource dataSource;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("isAuthenticated()");
    }

    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }
}

(2)客户端

客户端使用Spring Security OAuth2实现。在pom.xml文件中添加以下依赖:

代码语言:javascript复制
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.4.1</version>
</dependency>

然后,创建一个配置类,配置OAuth2的客户端和令牌存储:

代码语言:javascript复制
@Configuration
@EnableOAuth2Client
public class OAuth2ClientConfig {
    @Value("${oauth2.client.registration.my-client-1.client-id}")
    private String clientId;
    @Value("${oauth2.client.registration.my-client-1.client-secret}")
    private String clientSecret;
    @Value("${oauth2.client.provider.my-provider.token-uri}")
    private String accessTokenUri;
    @Value("${oauth2.client.provider.my-provider.authorization-uri}")
    private String userAuthorizationUri;
    @Value("${oauth2.client.provider.my-provider.user-info-uri}")
    private String userInfoUri;
    @Value("${oauth2.client.provider.my-provider.user-name-attribute}")
    private String usernameAttribute;

    @Autowired
    private OAuth2ClientContext oauth2ClientContext;

    @Bean
    public OAuth2RestTemplate oauth2RestTemplate() {
        OAuth2ProtectedResourceDetails resourceDetails = new AuthorizationCodeResourceDetails();
        resourceDetails.setClientId(clientId);
        resourceDetails.setClientSecret(clientSecret);
        resourceDetails.setAccessTokenUri(accessTokenUri);
        resourceDetails.setUserAuthorizationUri(userAuthorizationUri);
        resourceDetails.setUserInfoUri(userInfoUri);
        resourceDetails.setPreEstablishedRedirectUri("http://localhost:8080/login");
        resourceDetails.setUseCurrentUri(false);
        resourceDetails.setClientAuthenticationScheme(AuthenticationScheme.form);
        resourceDetails.setAuthenticationScheme(AuthenticationScheme.query);

        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, oauth2ClientContext);
        restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter()));
        return restTemplate;
    }
}

(3)安全通信

在客户端的REST API中,使用@PreAuthorize注解限制访问范围:

代码语言:javascript复制
@RestController
public class MyRestController {
    @Autowired
    private OAuth2RestTemplate oauth2RestTemplate;

    @GetMapping("/resource")
    @PreAuthorize("#oauth2.hasScope('read')")
    public String getResource() {
        return oauth2RestTemplate.getForObject("https://provider.com/api/resource", String.class);
    }
}

在这个示例中,客户端调用/provider/api/resource接口获取资源,但只有在令牌的访问范围包括read时才能成功调用。

0 人点赞