点击QQ界面的邮箱图标就能实现直接登录QQ邮箱、登录验证进入新浪微博之后关掉浏览器下次再登录时就不用输入用户名密码而可以直接登录新浪微博,想必这些熟悉的操作大家已经不只操作过上万遍了。但是大家是否知道这些会话跟踪登录时如何实现的捏,带着这些问题让我们进入下面的知识点解析。
在进入本文之前大家可以先了解下有关Session的原理和会话跟踪的相关知识:
http://blog.csdn.net/zhangwenlong136/article/details/9255339
有了前面的知识点之后,接下来我们来做一个简单的会话跟踪的设计与实现,不多说先上效果图:
1、本地自写浏览器登录效果图:
2、IE浏览器登录效果图
知识点解析:
1、Java关键代码
验证登录后台代码,对应http://localhost:8080/bbs/httclientloginCheck.shtml的验证:
package gdin.mvc.manager;
import gdin.mvc.db.Conn;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@SuppressWarnings("serial")
public class HttpClientLoginCheck extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String userName = req.getParameter("userName");
String password = req.getParameter("password");
Statement stmt = Conn.getStatement();
String sql = "select * from User1 where userName = '" + userName +"' and password = '" + password + "'";
try {
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
HttpSession session = req.getSession();
System.out.println(session.getId());
if(session.getAttribute("userName")==null)
{
session.setAttribute("userName", userName);
session.setAttribute("password", password);
session.setAttribute("id", rs.getInt("id"));
}
resp.setCharacterEncoding("GBK");
PrintWriter pw=resp.getWriter();
pw.println("<html>");
pw.println("<head>");
pw.println("</head>");
pw.println("<body>");
pw.println("SessionID=" + session.getId() + "#");
pw.println("</body>");
pw.println("</html>");
}
else {
resp.sendRedirect("loginResult.jsp");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
}
登录后台的的代码,对应http://localhost:8080/bbs/loginBackGround.shtml的验证后台登录:
package gdin.mvc.manager;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class LoginBackGround
*/
public class LoginBackGround extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
if(session.getAttribute("userName")!=null)
{
Cookie cookie=new Cookie("JSESSIONID", session.getId());//JSESSIONID在这里必须要大写,不然无法验证通过(具体原因不知)
resp.addCookie(cookie);
resp.sendRedirect("admin/backGround.jsp");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
过滤器
package gdin.mvc.filter;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Limits implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
HttpSession session = req.getSession(false);
System.out.println("request URL:" + req.getRequestURI());
System.out.println("session Id:" + session.getId());
if (session.getAttribute("userName") != null) {
// System.out.println("request cookie:" + req.getCookies().toString());
chain.doFilter(req, resp);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
/admin/background.jsp界面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>后台管理</title>
</head>
<frameset rows="80,*" border="5" bordercolor="#ebebeb">
<frame src="top.jsp" name="topFrame" scrolling="no"/>
<frameset cols="150,*">
<frame src="left.jsp" scrolling="no"/>
<frame src="listUsers.shtml" name="mainFrame"/>
</frameset>
</frameset>
</html>
2、C++关键代码分析
//---------------------------------------------------------------------------
//获取SessionID
void __fastcall TForm1::Button1Click(TObject *Sender)
{
//通过HttpClient去完成验证登录并获取服务器端传回来的SessionID
//在这里我是直接通过Html解析返回来的SessionID的,也可以采用Json或XML,这里为了方便演示就用html了
XHTTPClient *Client=new XHTTPClient();
UnicodeString strNewURL=URL->Text;
strNewURL+="?userName=" + UserName->Text + "&password=" + Password->Text;
UnicodeString strText=Client->Get(strNewURL);
int i=strText.Pos("SessionID");
int j=strText.Pos("=");
if(i>0 && j>i)
{
i=strText.Pos("#");
SessionID=strText.SubString(j+1,i-j-1);
}
delete Client;
}
//---------------------------------------------------------------------------
//本地浏览器登录
void __fastcall TForm1::Button2Click(TObject *Sender)
{
UnicodeString strNewURL="http://localhost:8080/bbs/loginBackGround.shtml";
strNewURL+=";jsessionid=" + SessionID;
strHttpUrl=strNewURL;
CppWebBrowser1->Navigate(strNewURL.c_str());
// http://localhost:8080/bbs/admin/listUsers.shtml;jsessionid=50F5BF44DDB4694C003F3A9BE0904CE8
}
//---------------------------------------------------------------------------
//IE浏览器登录
void __fastcall TForm1::Button3Click(TObject *Sender)
{
ShellExecute(Handle, _T("open"), strHttpUrl.t_str(), 0, 0, SW_SHOWNORMAL);
}
//---------------------------------------------------------------------------
难点解析:
1,URL重写的jsessionid必须小写,回传给客户端的Cookie:JSESSIONID必须大写,不然无法实现,这个具体的原因还不知。
2,也许你回问,那要是客户端的Cookie被禁止了那怎么办?这种情况下,你就只能纯粹借助URL重写Jsessionid了,而且页面必须动态生成的,这样才能把Jsessionid动态嵌入到每个链接里面。