An overview of the

Remember how we used to create an order?

Through the gateway, the order-service invokes the create method of the order-service, and then invokes the reduce and product-service nt methods of the Account-Service through feign for business logic processing.

When our project integrated OAuth2, we called the previous method discovery call exception. We checked the backend log and found the following error message:

org.springframework.security.authentication.InsufficientAuthenticationException: Full authentication is required to access this resource

Request processing failed; nested exception is feign.FeignException$Unauthorized: status 401 reading AccountFeign#reduce(String,BigDecimal)
Copy the code

The error message tells us that the interface is not authorized to cause the access exception. In fact, we have put the access_token on the header as follows:

Finally, through tracing the user-defined exception class, it is found that the Access_token is lost when the order-service accesses the Account-service and the accessToken obtained is null.

This section addresses the problem of access_token loss when using feign.

Code sample

Feign supports request interceptors. Before sending a request, you can perform operations on the sent template, such as setting the request first-class attributes. The custom RequestInterceptor only needs to implement the RequestInterceptor interface, which has a method of RequestTemplate type parameter. We can adjust the requested information based on the actual situation.

public interface RequestInterceptor {
    void apply(RequestTemplate var1);
}
Copy the code

We need to take the original request header and pass it to the downstream service. Create the FeignRequestInterceptor in the order-service and add @Configuration to it.

/** * Description: * Feign call request header missing between microservices *@author javadaily
 * @date2020/02/24 9:28 * /
@Configuration
@Slf4j
public class FeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        HttpServletRequest httpServletRequest =   getHttpServletRequest();
        if(httpServletRequest! =null){
            Map<String, String> headers = getHeaders(httpServletRequest);
            // Pass all request headers to prevent partial loss
            // You can also pass only authenticated headers here
            //requestTemplate.header("Authorization", request.getHeader("Authorization"));
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                template.header(entry.getKey(), entry.getValue());
            }
            log.debug("FeignRequestInterceptor:{}", template.toString()); }}private HttpServletRequest getHttpServletRequest(a) {
        try {
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        } catch (Exception e) {
            return null; }}/** * get the original request header */
    private Map<String, String> getHeaders(HttpServletRequest request) {
        Map<String, String> map = new LinkedHashMap<>();
        Enumeration<String> enumeration = request.getHeaderNames();
        if(enumeration! =null) {while(enumeration.hasMoreElements()) { String key = enumeration.nextElement(); String value = request.getHeader(key); map.put(key, value); }}returnmap; }}Copy the code

After the configuration is complete, restart the server, call the create method again, and return the response result normally.

series

SpringCloud Alibaba micro-service practice