java修改请求Header/Cookies,跳过身份验证

一、问题描述

    希望修改请求中的Header/Cookies。

二、环境

    语言:java
    项目脚手架:springboot

三、解决方式

1、基于反射(需要在InterceptorRegistry注入我们写的bean)

1.1 修改 Cookies

import org.apache.catalina.connector.RequestFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;

/**
 * @author chen-biao
 * @Date 2021/6/8 17:13
 */
public class ManagerAutoLoginInterceptor extends HandlerInterceptorAdapter {
    private static final Logger logger = LoggerFactory.getLogger(ManagerAutoLoginInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //调试发现,通过 postMan 发送的请求,request对应的实现类为: RequestFacade
        if (!(request instanceof RequestFacade)) {
            return true;
        }
        Field cookiesField = null;
        Request cookieRequest = null;
        RequestFacade rf = (RequestFacade) request;
        Class requestClass = rf.getClass();
        Field requestField = null;
        try {
            requestField = requestClass.getDeclaredField("request");
        } catch (Exception e) {
            logger.info("request is null.");
            return true;
        }
        requestField.setAccessible(true);
        Object requestObject = requestField.get(rf);
        if (requestObject instanceof Request) {
            cookieRequest = (Request) requestObject;
            requestClass = cookieRequest.getClass();
            try {
                cookiesField = requestClass.getDeclaredField("cookies");
            } catch (Exception e) {
                logger.info("Request cookiesField is null.");
                return true;
            }
        }
        if (null == cookiesField) {
            logger.error("auto-login:获取不到cookies,无法完成反射设值。");
            return true;
        }
        cookiesField.setAccessible(true);
        Cookie[] cookies = new Cookie[1];
        Cookie cookie = new Cookie("你希望设置的cookie key", "你希望设置的cookie value");
        cookies[0] = cookie;
        cookiesField.set(cookieRequest, cookies);
        logger.info("auto-login-end:自动设置请求token完成。");
        return true;
    }
}

1.2 修改 Header

import com.berchina.platform.security.SecurityContanst;
import org.apache.catalina.connector.RequestFacade;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.MimeHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;

/**
 * @author chen-biao
 * @Date 2021/6/8 18:13
 */
public class MobileAutoLoginInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(MobileAutoLoginInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(request instanceof RequestFacade)) {
            return true;
        }
        String httpToken = request.getHeader(SecurityContanst.USER_TOKEN_NAME);
        if (null != httpToken) {
            logger.info("auto-login:带有token,使用自带token进行后续操作。token: {}", httpToken);
            return true;
        }
        String headerName = "你希望这是的header名称";
        String headerValue = "你希望设置的header值";
        Class<? extends HttpServletRequest> requestClass = request.getClass();
        try {
            Field request1 = requestClass.getDeclaredField("request");
            request1.setAccessible(true);
            Object o = request1.get(request);
            Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
            coyoteRequest.setAccessible(true);
            Object o1 = coyoteRequest.get(o);
            Field headers = o1.getClass().getDeclaredField("headers");
            headers.setAccessible(true);
            MimeHeaders o2 = (MimeHeaders) headers.get(o1);
            o2.addValue(headerName);
            Field mimeHeadersHeaders = o2.getClass().getDeclaredField("headers");
            mimeHeadersHeaders.setAccessible(true);
            Object[] o3 = (Object[]) mimeHeadersHeaders.get(o2);
            for (Object om : o3) {
                Field nameBField = om.getClass().getDeclaredField("nameB");
                nameBField.setAccessible(true);
                MessageBytes nameB = (MessageBytes) nameBField.get(om);
                if (headerName.equals(nameB.getString())) {
                    Field valueBField = om.getClass().getDeclaredField("valueB");
                    valueBField.setAccessible(true);
                    MessageBytes valueB = MessageBytes.newInstance();
                    valueB.setString(headerValue);
                    valueBField.set(om, valueB);
                    logger.info("auto-login:设置的token:{}",headerValue );
                }
            }
        } catch (Exception e) {
            logger.error("auto-login:set token error.", e);
            return true;
        }
        logger.info("auto-login-end:自动设置请求token完成。");
        return true;
    }
}

2、基于代理模式 (通过注解:Component,ConditionalOnProperty,Configuration 可以做到代码无侵入)

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.Arrays;

/**
 * @author chen-biao
 * @Date 2021/6/9 8:23
 */
@Component
public class MobileAutoLoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String headerName = "你希望设置的header名称";
        String headerValue = "header值";
        String cookiesName = "cookies名称";
        String cookiesValue = "cookies值";

        HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper((HttpServletRequest) request) {
            /**
             * 当调用request.getHeader("token")时,则获取请求参数中token值并当做Header的值返回
             */
            @Override
            public String getHeader(String name) {
                // 先从原本的Request中获取头,如果为空且名字为token,则从返回自定义的值,否则返回原有的值
                String superHeader = super.getHeader(name);
                if (headerName.equals(name) && (null == superHeader || "".equals(superHeader.trim()))) {
                    return headerValue;
                }
                return superHeader;
            }

            @Override
            public Cookie[] getCookies() {
                Cookie[] cookies = super.getCookies();
                //纯新增
                if(null == cookies){
                    cookies = new Cookie[1];
                    cookies[0] = new Cookie(cookiesName,cookiesValue);
                    return cookies;
                }
                //原有数据
                for (Cookie cookie : cookies) {
                    if(cookiesName.equals(cookie.getName())){
                        cookie.setValue(cookiesValue);
                        return cookies;
                    }
                }
                //原有数据和新增
                cookies= Arrays.copyOf(cookies,cookies.length+1);
                cookies[cookies.length-1] = new Cookie(cookiesName,cookiesValue);
                return cookies;
            }
        };
        chain.doFilter(requestWrapper, response);
    }

    @Override
    public void destroy() {

    }
}

四、end

    好了,打完收工。有问题请评论探讨,3q。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容