spring cloud oauth2 feign 遇到的坑

来源:互联网 发布:打印机扫描软件 编辑:程序博客网 时间:2024/05/28 11:28
关于oauth2相关的内容这里不重复描述,在spring cloud中在管理内部api时鉴权相信有很多人会有疑问,这里描述两种比较low的用法,由于公司内部使用的是阿里云edas这里仅仅是记录一下,如果有更好的用法在请赐教,不喜勿喷!

客户端模式

提供三方jar包

这里写图片描述

  • 这里需要抽一个jar包,需要用到feign的为服务端直接利用maven模式引入feign即可
<dependencies>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-feign</artifactId>        </dependency>        <dependency>            <groupId>com.netflix.feign</groupId>            <artifactId>feign-okhttp</artifactId>            <version>8.18.0</version>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-oauth2</artifactId>        </dependency>    </dependencies>

核心类

  • CustomHystrixConcurrencyStrategy.java
  • Oauth2ClientProperties.java
  • OAuth2FeignAutoConfiguration.java
  • OAuth2FeignRequestInterceptor.java
package com.paascloud.security.feign;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;/** * The class Oauth 2 client properties. * * @author paascloud.net @gmail.com */@Data@ConfigurationProperties(prefix = "paascloud.oauth2.client")public class Oauth2ClientProperties {    private String id;    private String accessTokenUrl;    private String clientId;    private String clientSecret;    private String clientAuthenticationScheme;}
package com.paascloud.security.feign;import com.netflix.hystrix.strategy.HystrixPlugins;import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;import org.springframework.stereotype.Component;import java.util.concurrent.Callable;/** * The class Custom hystrix concurrency strategy. * * @author paascloud.net @gmail.com */@Componentpublic class CustomHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {    /**     * Instantiates a new Custom hystrix concurrency strategy.     */    public CustomHystrixConcurrencyStrategy() {        HystrixPlugins.getInstance().registerConcurrencyStrategy(this);    }    /**     * Wrap callable callable.     *     * @param <T>      the type parameter     * @param callable the callable     *     * @return the callable     */    @Override    public <T> Callable<T> wrapCallable(Callable<T> callable) {        return new HystrixContextWrapper<T>(callable);    }    /**     * The class Hystrix context wrapper.     *     * @param <V> the type parameter     *     * @author paascloud.net @gmail.com     */    public static class HystrixContextWrapper<V> implements Callable<V> {        private HystrixRequestContext hystrixRequestContext;        private Callable<V> delegate;        /**         * Instantiates a new Hystrix context wrapper.         *         * @param delegate the delegate         */        HystrixContextWrapper(Callable<V> delegate) {        this.hystrixRequestContext = HystrixRequestContext.getContextForCurrentThread();            this.delegate = delegate;        }        /**         * Call v.         *         * @return the v         *         * @throws Exception the exception         */        @Override        public V call() throws Exception {            HystrixRequestContext existingState = HystrixRequestContext.getContextForCurrentThread();            try {                HystrixRequestContext.setContextOnCurrentThread(this.hystrixRequestContext);                return this.delegate.call();            } finally {                HystrixRequestContext.setContextOnCurrentThread(existingState);            }        }    }}
package com.paascloud.security.feign;import feign.Logger;import feign.RequestInterceptor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.client.Netty4ClientHttpRequestFactory;import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;import org.springframework.security.oauth2.client.OAuth2RestTemplate;import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;import org.springframework.security.oauth2.common.AuthenticationScheme;/** * The class O auth 2 feign auto configuration. * * @author paascloud.net @gmail.com */@Configuration@EnableConfigurationProperties(Oauth2ClientProperties.class)public class OAuth2FeignAutoConfiguration {    private final Oauth2ClientProperties oauth2ClientProperties;    /**     * Instantiates a new O auth 2 feign auto configuration.     *     * @param oauth2ClientProperties the oauth 2 client properties     */    @Autowired    public OAuth2FeignAutoConfiguration(Oauth2ClientProperties oauth2ClientProperties) {        this.oauth2ClientProperties = oauth2ClientProperties;    }    /**     * Resource details client credentials resource details.     *     * @return the client credentials resource details     */    @Bean("paascloudClientCredentialsResourceDetails")    public ClientCredentialsResourceDetails resourceDetails() {        ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();        details.setId(oauth2ClientProperties.getId());        details.setAccessTokenUri(oauth2ClientProperties.getAccessTokenUrl());        details.setClientId(oauth2ClientProperties.getClientId());        details.setClientSecret(oauth2ClientProperties.getClientSecret());        details.setAuthenticationScheme(AuthenticationScheme.valueOf(oauth2ClientProperties.getClientAuthenticationScheme()));        return details;    }    /**     * O auth 2 rest template o auth 2 rest template.     *     * @return the o auth 2 rest template     */    @Bean("paascloudOAuth2RestTemplate")    public OAuth2RestTemplate oAuth2RestTemplate() {        final OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(resourceDetails(), new DefaultOAuth2ClientContext());        oAuth2RestTemplate.setRequestFactory(new Netty4ClientHttpRequestFactory());        return oAuth2RestTemplate;    }    /**     * Oauth 2 feign request interceptor request interceptor.     *     * @param oAuth2RestTemplate the o auth 2 rest template     *     * @return the request interceptor     */    @Bean    public RequestInterceptor oauth2FeignRequestInterceptor(@Qualifier("paascloudOAuth2RestTemplate") OAuth2RestTemplate oAuth2RestTemplate) {        return new OAuth2FeignRequestInterceptor(oAuth2RestTemplate);    }    /**     * Feign logger level logger . level.     *     * @return the logger . level     */    @Bean    Logger.Level feignLoggerLevel() {        return Logger.Level.FULL;    }}
package com.paascloud.security.feign;import feign.RequestInterceptor;import feign.RequestTemplate;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.security.oauth2.client.OAuth2RestTemplate;import org.springframework.util.Assert;/** * The class O auth 2 feign request interceptor. * * @author paascloud.net @gmail.com */public class OAuth2FeignRequestInterceptor implements RequestInterceptor {    private static final String AUTHORIZATION_HEADER = "Authorization";    private static final String BEARER_TOKEN_TYPE = "bearer";    private final OAuth2RestTemplate oAuth2RestTemplate;    /**     * Instantiates a new O auth 2 feign request interceptor.     *     * @param oAuth2RestTemplate the o auth 2 rest template     */    OAuth2FeignRequestInterceptor(OAuth2RestTemplate oAuth2RestTemplate) {        Assert.notNull(oAuth2RestTemplate, "Context can not be null");        this.oAuth2RestTemplate = oAuth2RestTemplate;    }    /**     * Apply.     *     * @param template the template     */    @Override    public void apply(RequestTemplate template) {        template.header(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE,  oAuth2RestTemplate.getAccessToken().toString()));    }}

调用端配置

  1. 引入maven依赖
<dependency>            <groupId>com.liuzm.paascloud.common</groupId>            <artifactId>paascloud-security-feign</artifactId>            <version>1.0-SNAPSHOT</version></dependency>
  1. @FeignClient加入configuration属性
/** * The interface Mdc product feign api. * @author paascloud.net@gmail.com */@FeignClient(value = "paascloud-provider-mdc", configuration = OAuth2FeignAutoConfiguration.class, fallback = MdcProductFeignHystrix.class)public interface MdcProductFeignApi {    /**     * Update product stock by id int.     *     * @param productDto the product dto     *     * @return the int     */    @RequestMapping(value = "/api/product/updateProductStockById", method = RequestMethod.POST)    int updateProductStockById(@RequestBody ProductDto productDto);}

认证服务器配置

@Override    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {        clients.withClientDetails(restClientDetailsService);    }
package com.paascloud.provider.security;import com.paascloud.security.core.properties.OAuth2ClientProperties;import com.paascloud.security.core.properties.SecurityProperties;import org.apache.commons.lang3.ArrayUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;import org.springframework.security.oauth2.provider.ClientDetails;import org.springframework.security.oauth2.provider.ClientDetailsService;import org.springframework.security.oauth2.provider.ClientRegistrationException;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;/** * The class Rest client details service. * * @author paascloud.net @gmail.com */@Component("restClientDetailsService")public class RestClientDetailsServiceImpl implements ClientDetailsService {    private ClientDetailsService clientDetailsService;    @Autowired    private SecurityProperties securityProperties;    /**     * Init.     */    @PostConstruct    public void init() {        InMemoryClientDetailsServiceBuilder builder = new InMemoryClientDetailsServiceBuilder();        if (ArrayUtils.isNotEmpty(securityProperties.getOauth2().getClients())) {            for (OAuth2ClientProperties client : securityProperties.getOauth2().getClients()) {                builder.withClient(client.getClientId())                        .secret(client.getClientSecret())                        .authorizedGrantTypes("refresh_token", "password", "client_credentials")                        .accessTokenValiditySeconds(client.getAccessTokenValidateSeconds())                        .refreshTokenValiditySeconds(2592000)                        .scopes(client.getScope());            }        }        try {            clientDetailsService = builder.build();        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * Load client by client id client details.     *     * @param clientId the client id     *     * @return the client details     *     * @throws ClientRegistrationException the client registration exception     */    @Override    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {        return  clientDetailsService.loadClientByClientId(clientId);    }}

bootstrap.yml配置

security:    oauth2:      tokenStore: jwt      clients[0]:        clientId: paascloud-client-uac        clientSecret: paascloudClientSecret        accessTokenValidateSeconds: 7200        scope: "*"      clients[1]:        clientId: paascloud-browser        clientSecret: paascloudClientSecret        accessTokenValidateSeconds: 7200        scope: "*"      clients[2]:        clientId: paascloud-client-gateway        clientSecret: paascloudClientSecret        accessTokenValidateSeconds: 7200        scope: "*"      clients[3]:        clientId: paascloud-client-zipkin        clientSecret: paascloudClientSecret        accessTokenValidateSeconds: 7200        scope: "*"      clients[4]:        clientId: paascloud-client-mdc        clientSecret: paascloudClientSecret        accessTokenValidateSeconds: 7200        scope: "*"      clients[5]:        clientId: paascloud-client-omc        clientSecret: paascloudClientSecret        accessTokenValidateSeconds: 7200        scope: "*"      clients[6]:        clientId: paascloud-client-opc        clientSecret: paascloudClientSecret        accessTokenValidateSeconds: 7200        scope: "*"

到此客户端模式配置完成!

基于spring security

开放权限,利用url规范来规划客户端的url不通过auth2鉴权,这里唯一的区别是在feign拦截器里处理的逻辑改一下,代码如下

@Autowiredprivate OAuth2ClientContext context;@Override    public void apply(RequestTemplate template) {        if(context.getAccessToken() != null && context.getAccessToken().getValue() != null && OAuth2AccessToken.BEARER_TYPE.equalsIgnoreCase(context.getAccessToken().getTokenType()) ){            template.header("Authorization", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, context.getAccessToken().getValue()));        }    }
原创粉丝点击