网站自动登录操作分析,我以CSDN用户登录功能为例说明,
1.进入csdn网站的登录界面 地址: CSDN用户登录界面 界面效果如下:
2.输入正确的用户名和密码,并且勾选上 下次自动登录功能
3.点击登录,如果成功登录,就会跳转到登陆成功的界面.
4.如果你再去点击CSDN用户登录界面 看看什么效果,你会发现,打不开此登录界面,直接跳转到了如下图界面:
5.可以看到此时,已经完成了自动登录的功能模块.
根据以上分析,我结合Java Web中的Filter和Cookie完成一个网站自动登录的功能模块.
1.编写登录界面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
${requestScope.msg}<br/>
<form action="${pageContext.request.contextPath}/AdminOper.do" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="name"/></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="pass"/></td>
</tr>
<tr>
<td colspan="2">
<input type="radio" name="day" checked="checked" value="7">一周
<input type="radio" name="day" value="30">一月
<input type="radio" name="day" value="90">三个月
</td>
</tr>
<tr>
<td><input type="checkbox" name="mark" value="mark"/></td>
<td>下次自动登陆</td>
</tr>
<tr>
<td> <input type="submit" value="登陆"/></td>
<td><input type="reset" value="重置"/></td>
</tr>
</table>
<input type="hidden" name="oper" value="login"/>
</form>
</body>
</html>
效果如下:
2.登录界面处理的servlet类.
package www.csdn.net.day56.servlet;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
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 sun.misc.BASE64Encoder;
import com.sun.mail.util.BASE64EncoderStream;
import www.csdn.net.day56.bean.Admin;
import www.csdn.net.day56.dao.AdminDao;
import www.csdn.net.day56.dao.impl.AdminDaoImpl;
import www.csdn.net.day56.service.AdminService;
import www.csdn.net.day56.service.impl.AdminServiceImpl;
public class AdminServlet extends HttpServlet {
private AdminService adminService = new AdminServiceImpl();
private long expires = 24 * 60 * 60; // 1天
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String method = request.getMethod();
System.out.println("请求的方法::::" + method);
// 获取请求参数中 操作的标识符
String oper = request.getParameter("oper");
if ("login".equals(oper)) {
// 处理登陆
// 获取用户名和密码
String name = request.getParameter("name");
String pass = request.getParameter("pass");
//获取标记 是否自动登录标识符
String mark = request.getParameter("mark");
// 验证用户名和密码是否正确
Admin entity = adminService.checkLogin(name, pass);
if (entity != null) {
// 判断是自动登录处理
if ("mark".equals(mark)) {
// 获取默认记住的天数
String day = request.getParameter("day");
// 转换成有效的时间
expires = Integer.valueOf(day) * expires;
// 声明cookie
Cookie autoCookie = null;
// 获取所有cookie
Cookie cookies[] = request.getCookies();
// 遍历cookie
for (Cookie cookie : cookies) {
// 判断是否存在自动登陆记录
if ("autologin".equals(cookie.getName())) {
autoCookie = cookie; // 赋值
// 当cookie存在的时候,我需要重新设置值
long time = (System.currentTimeMillis() + expires * 1000);
//cookie拼接的value值,(可以根据自己的想法设计)
String newValue = name + ":" + time + ":"
+ md5Value(name + ":" + pass + ":" + time);
//设置值
autoCookie .setValue(newValue);
} else {
// 不存在创建
// name+":"+time+":"+md5(name:pass:time)
long time = System.currentTimeMillis() + expires
* 1000;
//cookie拼接的value值,(可以根据自己的想法设计)
String cookieValue = name + ":" + time + ":"
+ md5Value(name + ":" + pass + ":" + time);
//创建cookie
autoCookie = new Cookie("autologin", cookieValue);
}
}
autoCookie.setMaxAge((int) expires);
autoCookie.setPath("/day56");
// 添加cookie
response.addCookie(autoCookie);
}
// admin存入到session
request.getSession().setAttribute("admin", entity);
// 成功登陆后的操作
request.getRequestDispatcher("./sc.jsp").forward(request,
response);
} else {
request.setAttribute("msg", "用户名或者密码错误");
request.getRequestDispatcher("./index.jsp").forward(request,
response);
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
/**
* md5加密处理
* @param value
* @return
*/
public String md5Value(String value) {
try {
MessageDigest digest = MessageDigest.getInstance("md5");
byte result[] = digest.digest(value.getBytes());
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(result);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
}
3.有关自动完成登录过滤器的代码如下
package www.csdn.net.day56.filter;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sun.misc.BASE64Encoder;
import www.csdn.net.day56.bean.Admin;
import www.csdn.net.day56.service.AdminService;
import www.csdn.net.day56.service.impl.AdminServiceImpl;
public class AutoLoginFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
// 造型对象
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 1.首先判断sesion中有没有admin
Object object = request.getSession().getAttribute("admin");
// 如果session中有用户
if (object != null) {
// 跳转到成功登录的界面
request.getRequestDispatcher("./sc.jsp").forward(request, response);
return;
}
/*---------------------------以下是当session中不存在admin信息时候的处理---------------------------------*/
// 2.判断cookie中是否存在 autologin标识符 的cookie对象
// 声明cookie
Cookie autoCookie = null;
// 获取所有的cookie
Cookie cookies[] = request.getCookies();
// 如果没有cookie信息,就继续执行login.do,跳转到login.jsp页面
if (cookies != null) {
// 如果有,就遍历cookie
for (Cookie cookie : cookies) {
// 判断cookie中是否有autologin标识符的cookie
if ("autologin".equals(cookie.getName())) {
autoCookie = cookie; // 如果有 就赋值给临时变量autoCookie
}
}
// 3. 判断autoCookie是否等于null
if (autoCookie == null) {
// 如果等于null,则继续执行login.jsp页面
chain.doFilter(request, response);
return;
}
// 3.如果autoCookie不等于null,就判断cookie的值
// 获取cookie值
String value = autoCookie.getValue();
// 拆分cookie的值
String temp[] = value.split(":");
System.out.println(temp.length);
// 判断长度 是否等于自己拼接的长度
if (temp.length != 3) {
// 如果不等于3,则继续执行login.jsp页面
chain.doFilter(request, response);
return;
}
// 获取cookie拆分的各个值
String name = temp[0]; // 用户名
String time = temp[1];// 获取有效时间
String service_md5Value = temp[2];// 获取md5的加密后的字符
// 4.判断cookie是否失效
if (Long.valueOf(time) <= System.currentTimeMillis()) {
// 如果失效,则继续执行login.jsp页面
chain.doFilter(request, response);
return;
}
// 5.如果cookie没有失效,根据用户名,去查询用户信息
AdminService adminService = new AdminServiceImpl();
// 查询用户信息
Admin entity = adminService.checkLogin(name);
System.out.println(entity+"0000");
// 判断用户是否为null
if (entity == null) {
// 如果没有查询的用户,则继续执行login.jsp页面
chain.doFilter(request, response);
return;
}
// 按照服务器拼接的字符的方式,拼接md5加密的字符串
String md5Temp = entity.getName() + ":" + entity.getPass() + ":"
+ time;
// 判断md5加密后和服务器端加密的字符是否相等
if (!(md5Value(md5Temp).equals(service_md5Value))) {
// 在不相等的情况下,则继续执行login.jsp页面
chain.doFilter(request, response);
return;
}
// 如果满足了cookie取值判断的所有结果,则跳转到成功登录的界面.
request.getSession().setAttribute("admin", entity);
request.getRequestDispatcher("./sc.jsp").forward(request, response);
} else {
// 在没有cookie信息的时候,则继续login.jsp页面
chain.doFilter(request, response);
return;
}
}
// md5加密字符串
public String md5Value(String value) {
try {
MessageDigest digest = MessageDigest.getInstance("md5");
byte result[] = digest.digest(value.getBytes());
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(result);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
4.在web.xml文件中配置过滤器
<filter>
<filter-name>AutoLoginFilter</filter-name>
<filter-class>www.csdn.net.day56.filter.AutoLoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AutoLoginFilter</filter-name>
<url-pattern>/login.jsp</url-pattern>
</filter-mapping>
5.以上功能模块中涉及到的类或者接口如下:
1.Admin.java类
package www.csdn.net.day56.bean;
import java.io.Serializable;
public class Admin implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String pass;
public Admin() {
super();
// TODO Auto-generated constructor stub
}
public Admin(Integer id, String name, String pass) {
super();
this.id = id;
this.name = name;
this.pass = pass;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
}
2.BaseDao接口
package www.csdn.net.day56.dao;
public interface BaseDao<T, PK> {
}
3.AdminDao接口
package www.csdn.net.day56.dao;
import www.csdn.net.day56.bean.Admin;
public interface AdminDao extends BaseDao<Admin,Integer>{
/**
* 用户登录验证的操作
* @param name
* @param pass
* @return
*/
public Admin checkLogin(String name,String pass);
/**
*
* @param name
* @return
*/
public Admin checkLogin(String name);
}
4.AdminDao接口的实现类
package www.csdn.net.day56.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import util.DBConn;
import www.csdn.net.day56.bean.Admin;
import www.csdn.net.day56.dao.AdminDao;
public class AdminDaoImpl implements AdminDao {
private Connection conn;
private PreparedStatement pstmt;
private ResultSet rs;
@Override
public Admin checkLogin(String name, String pass) {
Admin entity = null;
conn = DBConn.getConn();
String sql = "select * from admin where name=? and pass=? ";
try {
pstmt = conn.prepareStatement(sql);
int index = 1;
pstmt.setString(index++, name);
pstmt.setString(index++, pass);
rs = pstmt.executeQuery();
if (rs.next()) {
entity = new Admin();
entity.setId(rs.getInt("id"));
entity.setName(rs.getString("name"));
entity.setPass(rs.getString("pass"));
}
} catch (Exception e) {
} finally {
DBConn.release(rs, pstmt);
}
return entity;
}
@Override
public Admin checkLogin(String name) {
Admin entity = null;
conn = DBConn.getConn();
String sql = "select * from admin where name=? ";
try {
pstmt = conn.prepareStatement(sql);
int index = 1;
pstmt.setString(index++, name);
rs = pstmt.executeQuery();
if (rs.next()) {
entity = new Admin();
entity.setId(rs.getInt("id"));
entity.setName(rs.getString("name"));
entity.setPass(rs.getString("pass"));
}
} catch (Exception e) {
} finally {
DBConn.release(rs, pstmt);
}
return entity;
}
}
5.BaseService接口
package www.csdn.net.day56.service;
public interface BaseService<T, PK> {
}
6.AdminService接口
package www.csdn.net.day56.service;
import www.csdn.net.day56.bean.Admin;
public interface AdminService extends BaseService<Admin, Integer> {
/**
* 用户登录验证的操作
* @param name
* @param pass
* @return
*/
public Admin checkLogin(String name,String pass);
/**
*
* @param name
* @return
*/
public Admin checkLogin(String name);
}
7.AdminService接口的实现类
package www.csdn.net.day56.service.impl;
import www.csdn.net.day56.bean.Admin;
import www.csdn.net.day56.dao.AdminDao;
import www.csdn.net.day56.dao.impl.AdminDaoImpl;
import www.csdn.net.day56.service.AdminService;
public class AdminServiceImpl implements AdminService {
private AdminDao adminDao = new AdminDaoImpl();
@Override
public Admin checkLogin(String name, String pass) {
Admin entity = adminDao.checkLogin(name, pass);
return entity;
}
@Override
public Admin checkLogin(String name) {
return adminDao.checkLogin(name);
}
}
8.工具类
package util;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import org.apache.commons.io.FileUtils;
public class DBConn {
private static Connection conn;
private DBConn() {
}
public static Connection getConn() {
try {
if (conn == null) {
// 创建集合对象
Properties properties = new Properties();
// 装载
properties.load(DBConn.class.getClassLoader()
.getResourceAsStream("db.properties"));
// 加载驱动程序
Class.forName(properties.getProperty("driverClassName"));
// 获取连接对象
conn = DriverManager.getConnection(
properties.getProperty("url"),
properties.getProperty("user"),
properties.getProperty("pass"));
// 修改事务 为手动提交方式
conn.setAutoCommit(false);
}
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
public static void update(String sql, Object params[],
PreparedStatement pstmt) throws Exception {
try {
pstmt = getConn().prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
pstmt.executeUpdate();
conn.commit();
} catch (Exception e) {
conn.rollback();
e.printStackTrace();
} finally {
release(null, pstmt);
}
}
public static void release(ResultSet rs, PreparedStatement pstmt) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
下面进行效果演示说明
1.打开登录界面,输入正确的用户名和密码,勾选上自动登录操作.
2.点击登录按钮,登录成功后,跳转到sc.jsp页面
3.重新进入登录界面
发现,完成了自动登录的功能模块.
如果你关闭tomcat,重新启动,你会发现,只要在cookie的有效时间中,并且用户名和密码没有做修改的情况下,只要你进入登录界面.用户就会自动登录,并跳转到sc.jsp页面.效果同上图.