您好,登錄后才能下訂單哦!
本篇內容主要講解“spring cloud oauth2 feign遇到的坑怎么解決”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“spring cloud oauth2 feign遇到的坑怎么解決”吧!
關于oauth3相關的內容這里不重復描述,在spring cloud中在管理內部api時鑒權相信有很多人會有疑問,這里描述兩種比較low的用法。
提供三方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-oauth3</artifactId> </dependency> </dependencies>
核心類
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 */ @Component public 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.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依賴
<dependency> <groupId>com.liuzm.paascloud.common</groupId> <artifactId>paascloud-security-feign</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
@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: "*"
到此客戶端模式配置完成!
開放權限,利用url規范來規劃客戶端的url不通過auth3鑒權,這里唯一的區別是在feign攔截器里處理的邏輯改一下,代碼如下
@Autowired private 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())); } }
在授權服務里,用戶通過用戶名密碼,或者手機和驗證碼等方式登陸之后,在http頭里會有授權的標識,在客戶端調用時,需要添加當時有效的token才可以正常訪問被授權的頁面。
Content-Type:application/json Authorization:Bearer d79c064c-8675-4047-a119-fac692e447e8
而在業務層里,服務與服務之間使用feign來實現調用,而授權的代碼我們可以通過攔截器實現,在feign請求之前,把當前服務的token添加到目標服務的請求頭就可以了
/** * 發送FeignClient設置Header信息. * http://www.itmuch.com/spring-cloud-sum/hystrix-threadlocal/ * Hystrix傳播ThreadLocal對象 */ @Component public 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遇到的坑怎么解決”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。