千家信息网

spring cloud oauth2 feign遇到的坑怎么解决

发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,本篇内容主要讲解"spring cloud oauth2 feign遇到的坑怎么解决",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"spring cloud
千家信息网最后更新 2025年01月20日spring cloud oauth2 feign遇到的坑怎么解决

本篇内容主要讲解"spring cloud oauth2 feign遇到的坑怎么解决",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"spring cloud oauth2 feign遇到的坑怎么解决"吧!

spring cloud oauth3 feign 遇到的坑

关于oauth3相关的内容这里不重复描述,在spring cloud中在管理内部api时鉴权相信有很多人会有疑问,这里描述两种比较low的用法。

客户端模式

提供三方jar包

这里需要抽一个jar包,需要用到feign的为服务端直接利用maven模式引入feign即可

                    org.springframework.cloud            spring-cloud-starter-feign                            com.netflix.feign            feign-okhttp            8.18.0                            org.springframework.cloud            spring-cloud-starter-oauth3            

核心类

  • CustomHystrixConcurrencyStrategy.java

  • Oauth3ClientProperties.java

  • OAuth3FeignAutoConfiguration.java

  • OAuth3FeignRequestInterceptor.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.oauth3.client")public class Oauth3ClientProperties {    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       the type parameter     * @param callable the callable     *     * @return the callable     */    @Override    public  Callable wrapCallable(Callable callable) {        return new HystrixContextWrapper(callable);    }    /**     * The class Hystrix context wrapper.     *     * @param  the type parameter     *     * @author paascloud.net @gmail.com     */    public static class HystrixContextWrapper implements Callable {        private HystrixRequestContext hystrixRequestContext;        private Callable delegate;        /**         * Instantiates a new Hystrix context wrapper.         *         * @param delegate the delegate         */        HystrixContextWrapper(Callable 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.oauth3.client.DefaultOAuth3ClientContext;import org.springframework.security.oauth3.client.OAuth3RestTemplate;import org.springframework.security.oauth3.client.token.grant.client.ClientCredentialsResourceDetails;import org.springframework.security.oauth3.common.AuthenticationScheme;/** * The class O auth 2 feign auto configuration. * * @author paascloud.net @gmail.com */@Configuration@EnableConfigurationProperties(Oauth3ClientProperties.class)public class OAuth3FeignAutoConfiguration {    private final Oauth3ClientProperties oauth3ClientProperties;    /**     * Instantiates a new O auth 2 feign auto configuration.     *     * @param oauth3ClientProperties the oauth 2 client properties     */    @Autowired    public OAuth3FeignAutoConfiguration(Oauth3ClientProperties oauth3ClientProperties) {        this.oauth3ClientProperties = oauth3ClientProperties;    }    /**     * Resource details client credentials resource details.     *     * @return the client credentials resource details     */    @Bean("paascloudClientCredentialsResourceDetails")    public ClientCredentialsResourceDetails resourceDetails() {        ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();        details.setId(oauth3ClientProperties.getId());        details.setAccessTokenUri(oauth3ClientProperties.getAccessTokenUrl());        details.setClientId(oauth3ClientProperties.getClientId());        details.setClientSecret(oauth3ClientProperties.getClientSecret());        details.setAuthenticationScheme(AuthenticationScheme.valueOf(oauth3ClientProperties.getClientAuthenticationScheme()));        return details;    }    /**     * O auth 2 rest template o auth 2 rest template.     *     * @return the o auth 2 rest template     */    @Bean("paascloudOAuth3RestTemplate")    public OAuth3RestTemplate oAuth3RestTemplate() {        final OAuth3RestTemplate oAuth3RestTemplate = new OAuth3RestTemplate(resourceDetails(), new DefaultOAuth3ClientContext());        oAuth3RestTemplate.setRequestFactory(new Netty4ClientHttpRequestFactory());        return oAuth3RestTemplate;    }    /**     * Oauth 2 feign request interceptor request interceptor.     *     * @param oAuth3RestTemplate the o auth 2 rest template     *     * @return the request interceptor     */    @Bean    public RequestInterceptor oauth3FeignRequestInterceptor(@Qualifier("paascloudOAuth3RestTemplate") OAuth3RestTemplate oAuth3RestTemplate) {        return new OAuth3FeignRequestInterceptor(oAuth3RestTemplate);    }    /**     * 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.oauth3.client.OAuth3RestTemplate;import org.springframework.util.Assert;/** * The class O auth 2 feign request interceptor. * * @author paascloud.net @gmail.com */public class OAuth3FeignRequestInterceptor implements RequestInterceptor {    private static final String AUTHORIZATION_HEADER = "Authorization";    private static final String BEARER_TOKEN_TYPE = "bearer";    private final OAuth3RestTemplate oAuth3RestTemplate;    /**     * Instantiates a new O auth 2 feign request interceptor.     *     * @param oAuth3RestTemplate the o auth 2 rest template     */    OAuth3FeignRequestInterceptor(OAuth3RestTemplate oAuth3RestTemplate) {        Assert.notNull(oAuth3RestTemplate, "Context can not be null");        this.oAuth3RestTemplate = oAuth3RestTemplate;    }    /**     * Apply.     *     * @param template the template     */    @Override    public void apply(RequestTemplate template) {        template.header(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE,  oAuth3RestTemplate.getAccessToken().toString()));    }}

调用端配置

引入maven依赖

            com.liuzm.paascloud.common            paascloud-security-feign            1.0-SNAPSHOT

@FeignClient加入configuration属性

/** * The interface Mdc product feign api. * @author paascloud.net@gmail.com */@FeignClient(value = "paascloud-provider-mdc", configuration = OAuth3FeignAutoConfiguration.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.OAuth3ClientProperties;import com.paascloud.security.core.properties.SecurityProperties;import org.apache.commons.lang3.ArrayUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.oauth3.config.annotation.builders.InMemoryClientDetailsServiceBuilder;import org.springframework.security.oauth3.provider.ClientDetails;import org.springframework.security.oauth3.provider.ClientDetailsService;import org.springframework.security.oauth3.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.getOauth3().getClients())) {            for (OAuth3ClientProperties client : securityProperties.getOauth3().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:    oauth3:      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不通过auth3鉴权,这里唯一的区别是在feign拦截器里处理的逻辑改一下,代码如下

@Autowiredprivate OAuth3ClientContext context;@Override    public void apply(RequestTemplate template) {        if(context.getAccessToken() != null && context.getAccessToken().getValue() != null && OAuth3AccessToken.BEARER_TYPE.equalsIgnoreCase(context.getAccessToken().getTokenType()) ){            template.header("Authorization", String.format("%s %s", OAuth3AccessToken.BEARER_TYPE, context.getAccessToken().getValue()));        }    }

spring cloud微服务增加oauth3权限后 feign调用报null

在授权服务里,用户通过用户名密码,或者手机和验证码等方式登陆之后,在http头里会有授权的标识,在客户端调用时,需要添加当时有效的token才可以正常访问被授权的页面。

Content-Type:application/jsonAuthorization:Bearer d79c064c-8675-4047-a119-fac692e447e8

而在业务层里,服务与服务之间使用feign来实现调用,而授权的代码我们可以通过拦截器实现,在feign请求之前,把当前服务的token添加到目标服务的请求头就可以了

一般是这样实现的

/** * 发送FeignClient设置Header信息. * http://www.itmuch.com/spring-cloud-sum/hystrix-threadlocal/ * Hystrix传播ThreadLocal对象 */@Componentpublic class TokenFeignClientInterceptor implements RequestInterceptor {  /**   * token放在请求头.   *   * @param requestTemplate 请求参数   */  @Override  public void apply(RequestTemplate requestTemplate) {    RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();    if (requestAttributes != null) {      HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();      requestTemplate.header("Authorization", request.getHeader("Authorization"));    }  }}

上面的拦截器代码没有什么问题,也很好理解,但事实上,当你的feign开启了hystrix功能,如果开启了,需要把hystrix的策略进行修改,默认是THREAD的,这个级别时ThreadLocal是空的,所以你的授权不能传给feign的拦截器.

hystrix:     command:         default:             execution:                 isolation:                     strategy: SEMAPHORE

到此,相信大家对"spring cloud oauth2 feign遇到的坑怎么解决"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

服务 客户 拦截器 配置 代码 内容 客户端 模式 权限 用户 学习 实用 更深 有效 三方 业务 之间 事实 事实上 兴趣 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器系统资源不足 服务器硬防护 软件开发的自学知识 没有域名的服务器需要备案吗 社保认证服务器错误 获取数据库一个字段最新数据 先学编程语言还是数据库语言 c 打开数据库文件 数据库如何关联word打印 网络安全主题班会心得体会一百字 属于回收数据库资源时进行的操作 数据软件开发价格品质保障 远程服务器突然无响应 倩女幽魂手游服务器不一致怎么办 山西网络服务器机箱是什么 rust开服务器怎么调无敌房 长沙好的软件开发公司 杭州孙悟空网络技术有限公司 服务器无响应路由器 某月某日铃声软件开发 linux怎么导入数据库 智能家居服务器维修 数据库一般多少条写入性能高 松江区直销网络技术哪家强 软件开发的七个文档 易语言数据库转换 小型服务器创业 广州黄埔特聘网络安全 芋头服务器哺乳期可以吃吗 浙江综合网络技术咨询产品
0