tomcat 7对sessionId的处理:
首先解析request请求中的sessionID:
从AjpProcessor.java的process(SocketWrapper<Socket> socket)调用CoyoteAdapter.process里面有的postParseRequest(org.apache.coyote.Request req, Request request,org.apache.coyote.Response res,
Response response) 就有解析获取sessionid的过程
-
-
-
- String sessionID = null;
- if (request.getServletContext().getEffectiveSessionTrackingModes()
- .contains(SessionTrackingMode.URL)) {
-
-
- sessionID = request.getPathParameter(
- SessionConfig.getSessionUriParamName(
- request.getContext()));
- if (sessionID != null) {
- request.setRequestedSessionId(sessionID);
- request.setRequestedSessionURL(true);
- }
- }
-
-
- parseSessionCookiesId(req, request);
- parseSessionSslId(request);
-
-
-
-
-
- protected void parseSessionSslId(Request request) {
- if (request.getRequestedSessionId() == null &&
- SSL_ONLY.equals(request.getServletContext()
- .getEffectiveSessionTrackingModes()) &&
- request.connector.secure) {
-
-
-
- request.setRequestedSessionId(
- request.getAttribute(SSLSupport.SESSION_ID_KEY).toString());
- request.setRequestedSessionSSL(true);
- }
- }
-
-
-
-
-
- protected void parseSessionCookiesId(org.apache.coyote.Request req, Request request) {
-
-
-
-
-
- Context context = (Context) request.getMappingData().context;
- if (context != null && !context.getServletContext()
- .getEffectiveSessionTrackingModes().contains(
- SessionTrackingMode.COOKIE)) {
- return;
- }
-
-
- Cookies serverCookies = req.getCookies();
- int count = serverCookies.getCookieCount();
- if (count <= 0) {
- return;
- }
-
- String sessionCookieName = SessionConfig.getSessionCookieName(context);
-
- for (int i = 0; i < count; i++) {
- ServerCookie scookie = serverCookies.getCookie(i);
- if (scookie.getName().equals(sessionCookieName)) {
-
- if (!request.isRequestedSessionIdFromCookie()) {
-
- convertMB(scookie.getValue());
- request.setRequestedSessionId
- (scookie.getValue().toString());
- request.setRequestedSessionCookie(true);
- request.setRequestedSessionURL(false);
- if (log.isDebugEnabled()) {
- log.debug(" Requested cookie session id is " +
- request.getRequestedSessionId());
- }
- } else {
- if (!request.isRequestedSessionIdValid()) {
-
- convertMB(scookie.getValue());
- request.setRequestedSessionId
- (scookie.getValue().toString());
- }
- }
- }
- }
-
- }
如果没有sessionId,则在request.getSession()的时候需要进行处理
上面会通过manager.createSession创建session,如果request请求带了sessionId,则传入该参数
,没有的话则会创建一个,并且会把sessionId放入response的cookie中
manager对应ManagerBase.java类,里面生成session的过程如下:
-
-
-
-
-
-
-
-
-
-
-
-
-
- @Override
- public Session createSession(String sessionId) {
-
- if ((maxActiveSessions >= 0) &&
- (getActiveSessions() >= maxActiveSessions)) {
- rejectedSessions++;
- throw new IllegalStateException(
- sm.getString("managerBase.createSession.ise"));
- }
-
-
- Session session = createEmptySession();
-
-
- session.setNew(true);
- session.setValid(true);
- session.setCreationTime(System.currentTimeMillis());
- session.setMaxInactiveInterval(this.maxInactiveInterval);
- String id = sessionId;
- if (id == null) {
- id = generateSessionId();
- }
- session.setId(id);
- sessionCounter++;
-
- SessionTiming timing = new SessionTiming(session.getCreationTime(), 0);
- synchronized (sessionCreationTiming) {
- sessionCreationTiming.add(timing);
- sessionCreationTiming.poll();
- }
- return (session);
-
- }
-
-
-
- protected String generateSessionId() {
-
- String result = null;
-
- do {
- if (result != null) {
-
-
-
- duplicates++;
- }
-
- result = sessionIdGenerator.generateSessionId();
-
- } while (sessions.containsKey(result));
-
- return result;
- }
- ..
sesseionIdGenerator生成sessionId的算法如下:
-
-
-
- public String generateSessionId() {
-
- byte random[] = new byte[16];
-
-
- StringBuilder buffer = new StringBuilder();
-
- int resultLenBytes = 0;
-
- while (resultLenBytes < sessionIdLength) {
- getRandomBytes(random);
- for (int j = 0;
- j < random.length && resultLenBytes < sessionIdLength;
- j++) {
- byte b1 = (byte) ((random[j] & 0xf0) >> 4);
- byte b2 = (byte) (random[j] & 0x0f);
- if (b1 < 10)
- buffer.append((char) ('0' + b1));
- else
- buffer.append((char) ('A' + (b1 - 10)));
- if (b2 < 10)
- buffer.append((char) ('0' + b2));
- else
- buffer.append((char) ('A' + (b2 - 10)));
- resultLenBytes++;
- }
- }
-
- if (jvmRoute != null && jvmRoute.length() > 0) {
- buffer.append('.').append(jvmRoute);
- }
-
- return buffer.toString();
- }
其中jvmRoute是为了防止tomcat集群导致的sessionId冲突,getRandomBytes(random);会通过随机算法生成16byte的字节数组,最终sessionId默认是生成16byte的字符串。
上面说到会把生成的sessionId存入response的cookie域中
- Cookie cookie =
- ApplicationSessionCookieConfig.createSessionCookie(
- context, session.getIdInternal(), isSecure());
-
- response.addSessionCookieInternal(cookie);
处理过程如下:
-
-
-
-
-
- public void addSessionCookieInternal(final Cookie cookie) {
- if (isCommitted()) {
- return;
- }
-
- String name = cookie.getName();
- final String headername = "Set-Cookie";
- final String startsWith = name + "=";
- final StringBuffer sb = generateCookieString(cookie);
- boolean set = false;
- MimeHeaders headers = coyoteResponse.getMimeHeaders();
- int n = headers.size();
- for (int i = 0; i < n; i++) {
- if (headers.getName(i).toString().equals(headername)) {
- if (headers.getValue(i).toString().startsWith(startsWith)) {
- headers.getValue(i).setString(sb.toString());
- set = true;
- }
- }
- }
- if (!set) {
- addHeader(headername, sb.toString());
- }
-
-
- }
如果header已经有这个sessionId的cookie,则更新,否则设置到header中。
|