Spring Cloud微服務之間用戶信息的轉遞


實現思路:

  1. 准備一個ThreadLocal變量,供線程之間共享。
  2. 每個微服對請求過濾,不管是經過網關的請求還是Feign的請求,如果是從網關過來的請求,從請求頭中獲取token並解析得到用戶信息,然后存入ThreadLocal變量;如果是feign請求,直接獲取請求頭中的用戶信息存入ThreadLocal中。
  3. 每個微服務在使用Feign調用別的微服務時,先從ThreadLocal里面取出user信息,並放在request的請求頭中。

ThreadLocal工具類:

package com.orange.common.system;

import com.orange.common.entity.UserInfo;

public class UserInfoContext {
    private static ThreadLocal<UserInfo> userInfo = new ThreadLocal<>();
    public final static String FEIGN_HEADER_USERINFO = "X-FEIGN-HEADER-USERINFO";

    public static UserInfo getUser() {
        return (UserInfo) userInfo.get();
    }

    public static void setUser(UserInfo user) {
        userInfo.set(user);
    }
}

承載用戶信息的實體類:

package com.orange.common.entity;

import lombok.Data;

import java.io.Serializable;

@Data
public class UserInfo implements Serializable {
    private Long userId;
    private String username;
}

微服務的請求過濾器

package com.orange.provider.component;


import com.alibaba.fastjson.JSON;
import com.orange.common.entity.UserInfo;
import com.orange.common.system.UserInfoContext;
import com.orange.common.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Slf4j
@Component
@Order(1)
public class UserInfoFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        initUserInfo((HttpServletRequest) servletRequest);
        filterChain.doFilter(servletRequest, servletResponse);
    }

    private void initUserInfo(HttpServletRequest request) {
        log.info("執行過濾器{}===================", "UserInfoFilter");
        String token = request.getHeader(JwtUtil.HEADER_TOKEN);
        log.info("獲取請求頭中的token:{}=======", token);
        String username = JwtUtil.getUsername(token);
        if (username != null) {
            UserInfo userInfo = new UserInfo();
            userInfo.setUsername(username);
            userInfo.setUserId(JwtUtil.getUserId(token));
            UserInfoContext.setUser(userInfo);
        }

        String userJson = request.getHeader(UserInfoContext.FEIGN_HEADER_USERINFO);
        log.info("獲取feign請求頭中的userInfo: {}=========", userJson);
        if (!StringUtils.isEmpty(userJson)) {
            UserInfo userInfo = JSON.parseObject(userJson, UserInfo.class);
            UserInfoContext.setUser(userInfo);
        }
    }
}

Feign請求攔截器

package com.orange.consumer.config;

import com.alibaba.fastjson.JSON;
import com.orange.common.entity.UserInfo;
import com.orange.common.system.UserInfoContext;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

@Slf4j
@Configuration
public class FeignConfig implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        log.info("feign請求攔截器============");
        //從應用上下文中取出user信息,放入Feign的請求頭中
        UserInfo user = UserInfoContext.getUser();
        log.info("應用上下文中的UserInfo:{}",user);
        if (user != null) {
            String userJson = JSON.toJSONString(user);
            try {
                requestTemplate.header(UserInfoContext.FEIGN_HEADER_USERINFO, userJson);
            } catch (Exception e) {
                log.info("用戶信息設置失敗=========");
            }
        }
    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM