好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用Feign设置Token鉴权调用接口

Feign设置Token鉴权调用接口

声明FeignClient 指定url

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

/**

  * CREATE BY songzhongjin ON 2021.05.08 15:58 星期六

  * DESC:feign方式 测试Deom

  */

@FeignClient (name = "testService" , url = "http://xxxxxx:8088" )

public interface FeignTest {

    /**

      * 通过feign调用接口

      * @param map

      * @return

      */

    @PostMapping (value = "/xxxxx/sys/login" )

    String login(Map<String, Object> map);

}

调用测试

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

/**

  * CREATE BY songzhongjin ON 2021.05.08 16:02 星期六

  * DESC:

  */

@RestController

public class Test {

    @Autowired

    FeignTest feignTest;

    @Autowired

    MetaDataService metaDataService;

    @PostMapping ( "/test" )

    public void test() {

        HashMap<String, Object> map = new HashMap<>();

        map.put( "user_id" , "xxx" );

        map.put( "password" , "xxxxx" );

        //调用 T 具体对象具体封装 

        MetaDataResponseVO<T> login = feignTest.login(map);

        List<T> data = login.getData();

        System.out.println(login.getData());

        //处理业务data

    }

}

返回对象可以封装demo

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

@Data

public class MetaDataResponseVO<T> implements Serializable {

    private static final long serialVersionUID = 316492198399615153L;

    /**

      * 状态码.

      */

    private String retcode;

    /**

      * 状态码描述.

      */

    private String retmsg;

    /**

      * 响应包体.

      */

    private List<T> data;

}

设置token 进行调用,Feign 的请求拦截器来统一添加请求头信息

先去implements RequestInterceptor 重写apply方法

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

/**

  * feign拦截器配置,调用前先鉴权.

  */

@Component

public class MetaDataFeignConfig implements RequestInterceptor {

      public FeignBasicAuthRequestInterceptor() {

    }

    /**

      * 给feign请求加上accessToken请求头.

      *

      * @param template

      */

    @Override

    public void apply(RequestTemplate template) {

        //feign加请求头 自定义fangjia.auth.token"

        template.header( "access_token" , System.getProperty( "fangjia.auth.token" ));

    }

}

配置拦截器

拦截器需要在 Feign 的配置中定义,代码如下所示。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

@Configuration

public class FeignConfiguration {

    /**

      * 日志级别

      *

      * @return

      */

    @Bean

    Logger.Level feignLoggerLevel() {

        return Logger.Level.FULL;

    }

    /**

      * 创建 Feign 请求拦截器, 在发送请求前设置认证的 Token, 各个微服务将 Token 设置 到环境变量中来达到通用的目的

      *

      * @return

      */

    @Bean

    public FeignBasicAuthRequestInterceptor basicAuthRequestInterceptor() {

        return new FeignBasicAuthRequestInterceptor();

    }

}

上面的准备好之后,我们只需要在调用业务接口之前先调用认证接口,然后将获取到的 Token 设置到环境变量中,通过 System.setProperty([fangjia.auth.token],token) 设置值,可以使用redis存放避免每次调用。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

    @Value ( "${feign-client.meta-data.user}" )

    private String userId;

    @Value ( "${feign-client.meta-data.password}" )

    private String password;

    private static final String METADATA_ACCESS_TOKEN = "metaDataAccessToken" ;

    /**

      * 获取token,设置到上下文.

      */

    public void signInMetaData() {

        //拿缓存

        String accessToken = redisUtils.get(METADATA_ACCESS_TOKEN);

        log.warn( "-----------从redis拿meta的token结果--token ={}-------------" , accessToken);

        //System.setProperty("fangjia.metadata.token",token) 设置token值

        System.setProperty( "feign.metadata.token" , accessToken);

        log.warn( "--------------设置metaData接口鉴权结束-----------------" );

    }

token设置完成,我们需要在我们其他的feign文件中配置这个token,

注意配置对应的拦截器configuration ,MetaDataFeignConfig.class这个类就是我们设置头信息的

?

1

@FeignClient (name = [metaDataClient], url = [${feign-client.meta-data.url}], configuration = MetaDataFeignConfig. class )

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

package com.infinitus.dmm.openapi;

/**

  * 无限极元数据接口.

  *

  * @author 林志鹏

  * @date 2021/5/7

  */

@FeignClient (name = "metaDataClient" , url = "${feign-client.meta-data.url}" , configuration = MetaDataFeignConfig. class )

public interface MetaDataClient {

    /**

      * 拉取物理系统列表.

      */

    @RequestMapping (value = "/sc/mtdsystemlist" , method = RequestMethod.GET)

    MetaDataResponseVO<MetaDataSystem> pullPhysicalSystemList();

我们在调用该业务接口时候,需要先去调用设置头信息feign,在调用业务feign。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

  /**

      * 拉取物理系统列表.

      *

      * @return

      */

    public List<MetaDataSystem> pullPhysicalSystem() {

        //鉴权feign

        signInMetaData();

        //业务feign

        MetaDataResponseVO<MetaDataSystem> responseVO = metaDataClient.pullPhysicalSystemList();

        if (Objects.nonNull(responseVO)) {

            List<MetaDataSystem> data = responseVO.getData();

            if (Objects.nonNull(data) && !data.isEmpty()) {

                return data;

            }

        }

        return new ArrayList<>();

    }

补充

经过测试 鉴权接口调用成功,但是业务接口返回竟然超过10s feign默认的返回1秒就会触发熔断机制,所以我们需要设置feign的超时时间,可以指定FeignClient 名name 很人性化。

?

1

@FeignClient (name = [metaDataClient], url = [${feign-client.meta-data.url}])

?

1

2

3

4

5

6

7

8

9

#给metaDataClient服务设置超时时间 这里metaDataClient是我自己,全局的话metaDataClient替换default

feign:

   client:

    config:

      metaDataClient:

        connect-timeout: 50000

        read-timeout: 50000

   hystrix:

    enabled: false

Feign调用进行Token鉴权

项目场景

这边使用 两个springboot应用,中间通过feign来进行远程调用(是的没错,架构就是这么奇葩)。然后在调用feign的时候,希望可以进行token鉴权。

解决办法

请求进来时,通过拦截器,校验header的token,然后在业务中调用feignClient时,通过新加一个feign拦截器,拦截feign请求,把当前的header中的token添加到feign的请求头中去。实现token在链路中的传递。

具体实现

新增 feign 拦截器配置

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

/**

  * Feign请求拦截器配置.

  *

  * @author linzp

  * @version 1.0.0

  * @date 2021/4/16 21:19

  */

@Configuration

public class FeignInterceptorConfig implements RequestInterceptor {

    public FeignInterceptorConfig() {}

    @Override

    public void apply(RequestTemplate template) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();

        //设置token到请求头

        template.header(ConstantCommon.HEADER_TOKEN_KEY, request.getHeader(ConstantCommon.HEADER_TOKEN_KEY));

    }

}

然后在feignClient接口中,添加 == configuration = FeignInterceptorConfig.class==

注意有Bug!!!

注意!!!,这里会有个异常,获取到的request会是null。原因是hytrix隔离策略是thread,无法读到 threadLocal变量。

解决办法!!更改策略

在配置文件中新增如下配置,即可解决!

?

1

2

3

4

5

6

7

# 更换hystrix策略,解决无法传递threadLocal变量问题

hystrix:

    command:

        default:

            execution:

                isolation:

                    strategy: SEMAPHORE

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/weixin_42771651/article/details/116664108

查看更多关于使用Feign设置Token鉴权调用接口的详细内容...

  阅读:45次