SpringCloud 微服务之间调用免Token操作

基于Jeecg框架,修改FeignConfig配置。

package com.twqc.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.alibaba.fastjson.support.springfox.SwaggerJsonSerializer;
import com.twqc.common.config.mqtoken.UserTokenContext;
import com.twqc.common.constant.CommonConstant;
import com.twqc.common.util.DateUtils;
import com.twqc.common.util.PathMatcherUtil;
import com.twqc.config.sign.interceptor.SignAuthConfiguration;
import com.twqc.config.sign.util.HttpUtils;
import com.twqc.config.sign.util.SignUtil;
import feign.Feign;
import feign.Logger;
import feign.RequestInterceptor;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.SortedMap;

@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
@Slf4j
@Configuration
public class FeignConfig {

    @Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (null != attributes) {
                HttpServletRequest request = attributes.getRequest();
                log.debug("Feign request: {}", request.getRequestURI());
                // 将token信息放入header中
                String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
                if (token == null || "".equals(token)) {
                    token = request.getParameter("token");
                    if (token == null || "".equals(token)) {
                        // 从UserTokenContext中获取token。应用场景:feign调用时免登
                        token = UserTokenContext.getToken();
                    }
                }
                log.debug("Feign request token: {}", token);
                requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);

                //根据URL地址过滤请求 【字典表参数签名验证】
                if (PathMatcherUtil.matches(Arrays.asList(SignAuthConfiguration.urlList), requestTemplate.path())) {
                    try {
                        log.info("============================ [begin] fegin starter url ============================");
                        log.info(requestTemplate.path());
                        log.info(requestTemplate.method());
                        String queryLine = requestTemplate.queryLine();
                        if (queryLine != null && queryLine.startsWith("?")) {
                            queryLine = queryLine.substring(1);
                        }
                        log.info(queryLine);
                        if (requestTemplate.body() != null) {
                            log.info(new String(requestTemplate.body()));
                        }
                        SortedMap<String, String> allParams = HttpUtils.getAllParams(requestTemplate.path(), queryLine, requestTemplate.body(), requestTemplate.method());
                        String sign = SignUtil.getParamsSign(allParams);
                        log.info(" Feign request params sign: {}", sign);
                        log.info("============================ [end] fegin starter url ============================");
                        requestTemplate.header(CommonConstant.X_SIGN, sign);
                        requestTemplate.header(CommonConstant.X_TIMESTAMP, DateUtils.getCurrentTimestamp().toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                String token = UserTokenContext.getToken();
                log.debug("Feign request token: {}", token);
                requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
            }
        };
    }


    /**
     * Feign 客户端的日志记录,默认级别为NONE
     * Logger.Level 的具体级别如下:
     * NONE:不记录任何信息
     * BASIC:仅记录请求方法、URL以及响应状态码和执行时间
     * HEADERS:除了记录 BASIC级别的信息外,还会记录请求和响应的头信息
     * FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据
     */
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    /**
     * Feign支持文件上传
     *
     * @param messageConverters
     * @return
     */
    @Bean
    @Primary
    @Scope("prototype")
    public Encoder multipartFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }

    // update-begin--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ----------
    @Bean
    public Encoder feignEncoder() {
        return new SpringEncoder(feignHttpMessageConverter());
    }

    @Bean
    public Decoder feignDecoder() {
        return new SpringDecoder(feignHttpMessageConverter());
    }

    /**
     * 设置解码器为fastjson
     *
     * @return
     */
    private ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(this.getFastJsonConverter());
        return () -> httpMessageConverters;
    }

    private FastJsonHttpMessageConverter getFastJsonConverter() {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();

        List<MediaType> supportedMediaTypes = new ArrayList<>();
        MediaType mediaTypeJson = MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE);
        supportedMediaTypes.add(mediaTypeJson);
        converter.setSupportedMediaTypes(supportedMediaTypes);
        FastJsonConfig config = new FastJsonConfig();
        config.getSerializeConfig().put(JSON.class, new SwaggerJsonSerializer());
        config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
        converter.setFastJsonConfig(config);

        return converter;
    }
    // update-end--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ----------

}

获取临时Token

 /**
     * 获取临时Token
     *
     * @param username 用户名
     * @param password 密码
     * @return 临时Token
     */
    public static String getTemporaryToken(String username, String password) throws Exception {
        RedisUtil redisUtil = SpringContextUtils.getBean(RedisUtil.class);
        //模拟登录生成临时Token
        //参数说明:第一个参数是用户名、第二个参数是密码的加密串
        // 根据用户名获取用户密码
        String token = JwtUtil.sign(username, password);
        // 设置Token缓存有效时间为 5 分钟
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, 5 * 60 * 1000);
        return token;
    }

微服务调用前执行:

 UserTokenContext.setToken(UnmpUtil.getTemporaryToken(UnmpUtil.USER_NAME, UnmpUtil.PASSWORD));

参考:微服务之间调用免Token方案 · JeecgBoot 开发文档 · 看云

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud微服务开发中,可以通过以下几种方式来保存和使用access_token: 1. 在微服务中的配置文件中配置access_token 可以在微服务的配置文件(如application.yml或application.properties)中,添加access_token的配置项。然后在微服务中使用配置项来获取access_token。 示例: 在配置文件中添加以下配置项: ``` wechat: appid: your_appid secret: your_secret access-token: your_access_token ``` 然后在微服务中使用以下代码来获取access_token: ```java @Value("${wechat.access-token}") private String accessToken; ``` 2. 使用Redis等缓存服务保存access_token 可以使用Redis等缓存服务来保存access_token。在微服务中,通过调用缓存服务的API来获取和保存access_token。 示例: 使用Spring Boot集成Redis,在微服务中注入RedisTemplate,然后使用以下代码来获取和保存access_token: ```java @Autowired private RedisTemplate<String, String> redisTemplate; public String getAccessToken() { String accessToken = redisTemplate.opsForValue().get("access_token"); if (accessToken == null) { // 从微信服务器获取access_token accessToken = getAccessTokenFromWechatServer(); // 将access_token保存到Redis中 redisTemplate.opsForValue().set("access_token", accessToken, 7200, TimeUnit.SECONDS); } return accessToken; } ``` 3. 使用数据库保存access_token 可以使用数据库来保存access_token。在微服务中,通过调用数据库的API来获取和保存access_token。 示例: 使用Spring Data JPA集成数据库,在微服务中定义一个Access Token的实体类,然后使用以下代码来获取和保存access_token: ```java @Autowired private AccessTokenRepository accessTokenRepository; public String getAccessToken() { AccessToken accessToken = accessTokenRepository.findFirstByOrderByIdDesc(); if (accessToken == null || accessToken.isExpired()) { // 从微信服务器获取access_token accessToken = getAccessTokenFromWechatServer(); // 将access_token保存到数据库中 accessTokenRepository.save(accessToken); } return accessToken.getToken(); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值