受oauth2的client_credentials认证模式保护下API的openfeign使用方法

主要是3个配置文件,其他跟普通使用方法没啥区别

1.开发环境

springboot 2.7.4

java 17

认证服务:spring-security-oauth2-authorization-server 0.3.1

openfeign(客户端)用的springcloud 2021.0.4

2.maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2021.0.4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

3.application.properties配置参数

#根据实际认证服务器地址和端口号填写
spring.security.oauth2.client.provider.spring.issuer-uri=http://auth-server:9000
#auth-server是自己起的名字,待会儿配置文件里会用到
spring.security.oauth2.client.registration.auth-server.provider=spring
spring.security.oauth2.client.registration.auth-server.authorizationGrantType=client_credentials
spring.security.oauth2.client.registration.auth-server.clientId=theClientId
spring.security.oauth2.client.registration.auth-server.clientSecret=123
spring.security.oauth2.client.registration.auth-server.scope=openid

4.添加入口类注解

@SpringBootApplication
@EnableFeignClients
public class SpringcloudOpenfeignApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringcloudOpenfeignApplication.class, args);
    }

}

5.配置文件(共3个:2个针对openfeign的,1个针对springsecurity的)

import feign.RequestInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.*;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;

@Configuration
@RequiredArgsConstructor
public class OpenfeignConfiguration {
    private static final String CLIENT_REGISTRATION_ID="auth-server"; //auth-server对应application.properties里面的名字
    private final OAuth2AuthorizedClientService oAuth2AuthorizedClientService;
    private final ClientRegistrationRepository clientRegistrationRepository;

    //拦截器,每次访问在header里添加token
    @Bean
    public RequestInterceptor requestInterceptor(){
        ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId(CLIENT_REGISTRATION_ID);
        OAuthClientCredentialsFeignManager  manager = new OAuthClientCredentialsFeignManager(authorizedClientManager(), clientRegistration);
        return requestTemplate -> {
          requestTemplate.header("Authorization","Bearer "+ manager.getAccessToken());
        };
    }

    @Bean
    OAuth2AuthorizedClientManager authorizedClientManager() {
        OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
                .clientCredentials()
                .build();

        AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
                new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, oAuth2AuthorizedClientService);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
        return authorizedClientManager;
    }

}

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.registration.ClientRegistration;

import java.util.Collection;
import java.util.Collections;

import static java.util.Objects.isNull;

public class OAuthClientCredentialsFeignManager {
    private final OAuth2AuthorizedClientManager manager;
    private final Authentication principal;
    private final ClientRegistration clientRegistration;

    public OAuthClientCredentialsFeignManager(OAuth2AuthorizedClientManager manager, ClientRegistration clientRegistration){
        this.manager = manager;
        this.clientRegistration = clientRegistration;
        this.principal = createPrincipal();
    }

    private Authentication createPrincipal(){
        return new Authentication() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return Collections.emptyList();
            }

            @Override
            public Object getCredentials() {
                return null;
            }

            @Override
            public Object getDetails() {
                return null;
            }

            @Override
            public Object getPrincipal() {
                return this;
            }

            @Override
            public boolean isAuthenticated() {
                return false;
            }

            @Override
            public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {

            }

            @Override
            public String getName() {
                return clientRegistration.getClientId();
            }
        };
    }

    public String getAccessToken() {
        try {
            OAuth2AuthorizeRequest oAuth2AuthorizeRequest = OAuth2AuthorizeRequest
                    .withClientRegistrationId(clientRegistration.getRegistrationId())
                    .principal(principal)
                    .build();
            OAuth2AuthorizedClient client = manager.authorize(oAuth2AuthorizeRequest);
            if (isNull(client)) {
                throw new IllegalStateException("client credentials flow on " + clientRegistration.getRegistrationId() + " failed, client is null");
            }
            return client.getAccessToken().getTokenValue();
        } catch (Exception exp) {
            System.out.println("client credentials error " + exp.getMessage());
        }
        return null;
    }


}

springsecurity的相关配置

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
public class OAuth2WebSecurityConfigurerAdapter{

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                /*.authorizeRequests(authorizeRequests ->
                        authorizeRequests.anyRequest().authenticated()
                )*/
                .csrf().disable().oauth2Client();
        return http.build();
    }
}

6.client接口类

@FeignClient(value = "MeClient",
        url = "http://127.0.0.1:9000/"
)
public interface MeClient {
    @RequestMapping(method = RequestMethod.GET, value = "/user/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<SimpleResponse<Me>> getMe(@PathVariable("id") Integer id);
}

参考文章:

https://www.baeldung.com/spring-cloud-feign-oauth-token

https://amithkumarg.medium.com/spring-cloud-openfeign-oauth-2-0-68f75f06836f

tutorials/spring-cloud-modules/spring-cloud-openfeign at master · eugenp/tutorials · GitHub

https://kundan926.medium.com/microservices-communication-spring-boot-openfeign-client-credentials-e11ea9f7101b

Spring Cloud

7. Declarative REST Client: Feign

猜你喜欢

转载自blog.csdn.net/miaowansheng/article/details/127377878