修改HTTP header

下面这些header指令常常会用到,记得刚工作的时候写的一个网络磁盘就用到下载文件的header。header还可以用来控制客户端浏览器和代理服务器的缓存,这些以前有做过笔记.

  1. //用这个header指令来解决URL重写产生的404 header
  2. header('HTTP/1.1 200 OK');
  3. // 页面没找到
  4. header('HTTP/1.1 404 Not Found');
  5. // 访问受限
  6. header('HTTP/1.1 403 Forbidden');
  7. // The page moved permanently should be used for
  8. // all redrictions, because search engines know
  9. // what's going on and can easily update their urls.
  10. //页面被永久删除,可以告诉搜索引擎更新它们的urls
  11. //PS:第一次碰到这个指令,不知道能不能用来把自己的站点从搜索引擎中删除呢?
  12. header('HTTP/1.1 301 Moved Permanently');
  13. // 服务器错误
  14. header('HTTP/1.1 500 Internal Server Error');
  15. // 重定向到一个新的位置
  16. header('Location: http://www.example.org/');
  17. // 延迟一段时间后重定向
  18. header('Refresh: 10; url=http://www.example.org/');
  19. print 'You will be redirected in 10 seconds';
  20. // 也可以使用HTML语法来实现延迟
  21. // <meta http-equiv="refresh" content="10;http://www.example.org/ />
  22. // 覆盖 X-Powered-By value
  23. header('X-Powered-By: PHP/4.4.0');
  24. header('X-Powered-By: Brain/0.6b');
  25. // 内容语言 (en = English)
  26. header('Content-language: en');
  27. // 最后修改时间(在缓存的时候可以用到)
  28. $time = time() - 60; // or filemtime($fn), etc
  29. header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT');
  30. // 告诉浏览器要获取的内容还没有更新
  31. header('HTTP/1.1 304 Not Modified');
  32. // 设置内容的长度 (缓存的时候可以用到):
  33. header('Content-Length: 1234');
  34. // 用来下载文件:
  35. header('Content-Type: application/octet-stream');
  36. header('Content-Disposition: attachment; filename="example.zip"');
  37. header('Content-Transfer-Encoding: binary');
  38. // 加载要下载的文件:
  39. readfile('example.zip');
  40. // 禁止缓存当前文档:
  41. header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
  42. header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
  43. header('Pragma: no-cache');
  44. // 设置内容类型:
  45. header('Content-Type: text/html; charset=iso-8859-1');
  46. header('Content-Type: text/html; charset=utf-8');
  47. header('Content-Type: text/plain'); // plain text file
  48. header('Content-Type: image/jpeg'); // JPG picture
  49. header('Content-Type: application/zip'); // ZIP file
  50. header('Content-Type: application/pdf'); // PDF file
  51. header('Content-Type: audio/mpeg'); // Audio MPEG (MP3,...) file
  52. header('Content-Type: application/x-shockwave-flash'); // Flash animation
  53. // 显示登录对话框,可以用来进行HTTP认证
  54. header('HTTP/1.1 401 Unauthorized');
  55. header('WWW-Authenticate: Basic realm="Top Secret"');
  56. print 'Text that will be displayed if the user hits cancel or ';
  57. print 'enters wrong login data';
<think>我们面对的问题:修改HttpServletRequest的header值 根据提供的引用,有以下几种方法: 1. 使用自定义的RequestWrapper(如引用[2]和[4]所示) 创建一个HeaderMapRequestWrapper类,该类继承HttpServletRequestWrapper,并重写相关方法以支持修改header。 2. 使用反射直接修改(如引用[3]所示) 通过反射获取底层对象(如coyoteRequest)的headers字段,然后进行操作。 但是,需要注意的是: - HttpServletRequest是一个接口,我们通常使用的是容器(如Tomcat)提供的实现。 - 直接修改可能会破坏封装,且不同容器实现可能不同,反射方法可能不通用。 推荐方法:使用RequestWrapper(装饰器模式),这样更安全,且符合Servlet规范。 下面我们分别展示这两种方法: 方法一:使用自定义的RequestWrapper(推荐) 步骤: (1) 创建一个HeaderMapRequestWrapper类,继承HttpServletRequestWrapper。 (2) 添加一个Map用于存储自定义的header。 (3) 重写getHeader、getHeaders、getHeaderNames等方法,将自定义的header和原有的header合并。 如果需要添加或修改header,可以提供一个addHeader方法。 示例代码: ```java import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.util.*; public class HeaderMapRequestWrapper extends HttpServletRequestWrapper { private final Map<String, String> headerMap = new HashMap<>(); public HeaderMapRequestWrapper(HttpServletRequest request) { super(request); } public void addHeader(String name, String value) { headerMap.put(name, value); } @Override public String getHeader(String name) { String headerValue = headerMap.get(name); if (headerValue != null) { return headerValue; } return super.getHeader(name); } @Override public Enumeration<String> getHeaders(String name) { List<String> values = Collections.list(super.getHeaders(name)); if (headerMap.containsKey(name)) { values.add(headerMap.get(name)); } return Collections.enumeration(values); } @Override public Enumeration<String> getHeaderNames() { Set<String> names = new HashSet<>(Collections.list(super.getHeaderNames())); names.addAll(headerMap.keySet()); return Collections.enumeration(names); } } ``` 使用方式(如引用[2]和[4]): ```java // 在Filter或Interceptor中 HeaderMapRequestWrapper requestWrapper = new HeaderMapRequestWrapper(request); requestWrapper.addHeader("Token", "new token value"); // 然后继续传递包装后的request filterChain.doFilter(requestWrapper, response); ``` 方法二:使用反射修改(不推荐,因为容器依赖性强) 如引用[3]所示,通过反射获取底层实现类的headers对象(这里是Tomcat的MimeHeaders),然后进行操作。这种方法依赖于具体的Servlet容器实现(如Tomcat),如果更换容器(如Jetty)可能会失效。 示例代码(仅适用于Tomcat): ```java private void reflectSetHeader(HttpServletRequest request, String key, String value) { try { // 获取request的实际对象(可能是RequestFacade) Field requestField = request.getClass().getDeclField("request"); requestField.setAccessible(true); Object requestObj = requestField.get(request); // 获取coyoteRequest(Tomcat中的Request对象) Field coyoteRequestField = requestObj.getClass().getDeclField("coyoteRequest"); coyoteRequestField.setAccessible(true); Object coyoteRequestObj = coyoteRequestField.get(requestObj); // 获取headers字段 Field headersField = coyoteRequestObj.getClass().getDeclField("headers"); headersField.setAccessible(true); MimeHeaders headersObj = (MimeHeaders) headersField.get(coyoteRequestObj); // 修改header headersObj.removeHeader(key); headersObj.addValue(key).setString(value); } catch (Exception e) { // 异常处理 } } ``` 注意:反射方法需要处理异常,且由于不同容器实现不同,此代码可能不具有移植性。 总结: 推荐使用自定义RequestWrapper的方式,它是Servlet API推荐的方式(装饰器模式),安全且通用。 引用说明: [^1]: 通过分析源码,我们知道HttpServletRequest是接口,需要找到实现类。 [^2]: 使用RequestWrapper包装类来添加header。 [^3]: 通过反射修改底层Tomcat实现的header(不推荐)。 [^4]: 在Filter中使用RequestWrapper添加和修改header。 相关问题: 1. 如何在Spring Interceptor中修改HttpServletRequest的header? 2. 使用反射修改HttpServletRequest的header有什么风险? 3. 如何在Tomcat容器外修改HttpServletRequest的header? </think>### 修改 HttpServletRequest Header 的方法 在 Java Web 开发中,`HttpServletRequest` 的 Header 默认是只读的,但可通过以下两种安全可靠的方式修改: #### ✅ **推荐方法:使用 RequestWrapper(装饰器模式)** 通过自定义 `HttpServletRequestWrapper` 实现安全修改,兼容所有 Servlet 容器: ```java public class HeaderMapRequestWrapper extends HttpServletRequestWrapper { private final Map<String, String> customHeaders = new HashMap<>(); public HeaderMapRequestWrapper(HttpServletRequest request) { super(request); } // 添加/修改 Header public void addHeader(String name, String value) { customHeaders.put(name, value); } @Override public String getHeader(String name) { return customHeaders.containsKey(name) ? customHeaders.get(name) : super.getHeader(name); } @Override public Enumeration<String> getHeaderNames() { Set<String> names = new HashSet<>(Collections.list(super.getHeaderNames())); names.addAll(customHeaders.keySet()); return Collections.enumeration(names); } } ``` **使用示例(在 Filter 中)**: ```java public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { HttpServletRequest request = (HttpServletRequest) req; HeaderMapRequestWrapper wrappedRequest = new HeaderMapRequestWrapper(request); // 修改或新增 Header wrappedRequest.addHeader("Token", "new_token_value"); wrappedRequest.addHeader("Custom-Header", "data"); chain.doFilter(wrappedRequest, res); // 传递修改后的请求 } ``` > 此方法通过装饰器模式实现,无需反射,符合 Servlet 规范[^2][^4] #### 反射方法(不推荐) 仅适用于特定容器(如 Tomcat),存在兼容性风险: ```java private void reflectSetHeader(HttpServletRequest request, String key, String value) { try { // 获取 Tomcat 底层对象 Field requestField = request.getClass().getDeclaredField("request"); requestField.setAccessible(true); Object innerRequest = requestField.get(request); // 操作 Header 存储对象 Field coyoteRequestField = innerRequest.getClass().getDeclaredField("coyoteRequest"); coyoteRequestField.setAccessible(true); Object coyoteRequest = coyoteRequestField.get(innerRequest); // 修改 MimeHeaders Field headersField = coyoteRequest.getClass().getDeclaredField("headers"); headersField.setAccessible(true); MimeHeaders headers = (MimeHeaders) headersField.get(coyoteRequest); headers.removeHeader(key); headers.addValue(key).setString(value); } catch (Exception ex) { throw new RuntimeException("修改 Header 失败", ex); } } ``` > ⚠ 警告:此方法破坏封装性,不同容器实现差异会导致崩溃[^3] --- ### 关键区别 | **方法** | 安全性 | 容器兼容性 | 维护性 | 推荐场景 | |----------------|--------|------------|--------|------------------| | RequestWrapper | ✅ 高 | ✅ 全部 | ✅ 高 | 生产环境 | | 反射 | ❌ 低 | ❌ 仅 Tomcat| ❌ 低 | 临时调试(不推荐)| > 最佳实践:**优先使用 RequestWrapper**,它在 Filter 或 Interceptor 中通过装饰器模式实现安全修改[^2][^4],而反射方案会导致容器强耦合和升级风险[^3]。 --- ### 相关问题 1. `HttpServletRequestWrapper` 除了修改 Header 还能重写哪些请求数据? 2. 如何在 Spring Interceptor 中安全修改请求 Header? 3. Servlet 过滤器链中多次修改 Header 会有什么效果? 4. Tomcat 以外的 Web 容器(如 Jetty)如何修改 Header? 5. 修改请求 Header 会对 HTTP 会话管理产生什么影响?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值