在开发应用程序的过程中, 如果有多个应用, 通常会通过一个 portal 门户来集成, 这个 portal 是所有应用程序的入口, 用户一旦在 portal 登录之后, 进入另外一个系统, 就需要类似的单点登录(SSO). 进入各个子系统的时候, 就不需要再次登录, 当然类似的功能, 你可以通过专业的单点登录软件来实现, 也可以自己写数据库 token 等方式来实现。其实还有一个比较简单的方法, 就是通过 portal 封装已经登录过的用户的消息, 写到 HTTP header 之中, 然后把请求 forward 到各个子系统中去, 而各子系统从 HTTP header 中获取用户名, 作为是否登录过的校验或者合法的校验。总结了几种处理 HTTP Header 的方法:

利用 HttpServletRequest

import javax.servlet.http.HttpServletRequest;

//...
private HttpServletRequest request;

//get request headers
private Map<String, String> getHeadersInfo() {

  Map<String, String> map = new HashMap<String, String>();

  Enumeration headerNames = request.getHeaderNames();
  while (headerNames.hasMoreElements()) {
      String key = (String) headerNames.nextElement();
      String value = request.getHeader(key);
      map.put(key, value);
  }

  return map;
}

例如:

"headers" : {
    "Host" : "meniny.cn",
    "Accept-Encoding" : "gzip,deflate",
    "X-Forwarded-For" : "66.249.x.x",
    "X-Forwarded-Proto" : "http",
    "User-Agent" : "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
    "X-Request-Start" : "1389158003923",
    "Accept" : "*/*",
    "Connection" : "close",
    "X-Forwarded-Port" : "80",
    "From" : "googlebot(at)googlebot.com"
}

获取 user-agent

import javax.servlet.http.HttpServletRequest;

//...
private HttpServletRequest request;

private String getUserAgent() {
  return request.getHeader("user-agent");
}

例如:

Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)

利用 Spring MVC 获取 HttpRequest Header

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/site")
public class SiteController {

    @Autowired
    private HttpServletRequest request;

    @RequestMapping(value = "/{input:.+}", method = RequestMethod.GET)
    public ModelAndView getDomain(@PathVariable("input") String input) {

        ModelAndView modelandView = new ModelAndView("result");

        modelandView.addObject("user-agent", getUserAgent());
        modelandView.addObject("headers", getHeadersInfo());

        return modelandView;
    }

    //get user agent
    private String getUserAgent() {
        return request.getHeader("user-agent");
    }

    //get request headers
    private Map<String, String> getHeadersInfo() {

        Map<String, String> map = new HashMap<String, String>();

        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }

        return map;
    }

}

也许有人会说, HTTP Header 是可以模拟的, 那么自己可以构造一个用来欺骗这些系统, 是的, 的确是这样, 所以在用 HTTP Header 来传值得时候, 一定要记得, 所有的请求都必须经过 portal 来处理, 然后 forward 到各子系统, 就不会出现这个问题了。因为 portal 首先拦截用户发起的所有的请求, 如果是构造的用户, 在 portalsessiion 也是没有记录的, 仍然会跳转到登录页面, 如果在 protalsession 中记录, 而且 HTTP Header 中也有记录, 那么在子系统就是合法的用户, 然后自己可以根据一些要求处理业务逻辑了。