使用Filter实现用户自动登录

本文介绍了在Java Servlet中如何利用Filter实现用户自动登录的功能。通过Filter,可以统一处理请求,解决乱码、设置资源缓存和数据压缩等问题。详细步骤包括用户登录时的选择、发送自动登录Cookie、Filter检测与验证Cookie、配置Filter以及用户的注销操作。
摘要由CSDN通过智能技术生成

        java Servlet技术中Filter可以实现对请求的统一预处理,使请求有统一的可以控制的入口和出口,用Filter可以轻松解决全站的乱码问题:

	request.setCharacterEncoding(charset);  //post  get
	response.setCharacterEncoding(charset);
	response.setContentType("text/html;charset=" + charset); //设置在Filter参数中

对动态资源加禁止缓冲头:

	response.setDateHeader("Expires",-1);
	response.setHeader("Cache-Control","no-cache");
	response.setHeader("Pragma","no-cache");

对静态资源加缓存头:

	//1.获取到用户想访问的资源
	String uri = request.getRequestURI();
	//2.获取该资源的缓存时间
	int expires = 0;
	if(uri.endsWith(".jpg")){
		expires = Integer.parseInt(this.config.getInitParameter("jpg"));
	}else if(uri.endsWith(".css")){
		expires = Integer.parseInt(this.config.getInitParameter("css"));
	}else{
		expires = Integer.parseInt(this.config.getInitParameter("js"));
	}	
	response.setDateHeader("expires", System.currentTimeMillis()+expires*60*1000);

及实现数据压缩发生等

        使用Filter实现用户自动登录是Fiter能轻松实现的一项非常重要的功能,实现如下:

        1.用户登录时选择是否要自动登录:

<input name="autoLogin" type="checkbox" value="true" checked/>自动登录 

        2.servlet处理用户登录请求,如果选择自动登录,则发送一个可以实现自动登录的Cookie:

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            String name = request.getParameter("name");
            String password = request.getParameter("password");
            if (name.trim().equals("") || password.trim().equals("")) {
                request.getSession().setAttribute("login_message", "用户名或密码不能为空");
                response.sendRedirect(request.getContextPath() + "/servlet/login");
                return;
            }
            User user = new BusinessServiceImpl().login(name, password);
            if (user == null) {
                request.setAttribute("login_message", "用户名或密码不正确");
                request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
                return;
            }
            request.getSession().setAttribute("user", user);
            request.setAttribute("message", "登录成功");
            //添加自动登录cookie
            if (request.getParameter("autoLogin") != null && request.getParameter("autoLogin").equals("true")) {
                Cookie cookie = generateCookie(user);
                response.addCookie(cookie);
            }
            request.getRequestDispatcher("/message.jsp").forward(request, response);
        } catch (Exception e) {
            request.setAttribute("message", "未知错误");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            return;
        }
    }

    private static Cookie generateCookie(User user) throws NoSuchAlgorithmException {
        String name = user.getName();
        String password = user.getPassword();
        //测试,设置cookie有效其为60s
        int time = 60;
        //保存到时间
        long holdTime = System.currentTimeMillis() + time * 1000;
        String fixedValue = "hao";
        //cookie的值要包含唯一用户名与密码,以防止其他人生成用户cookie,并且要有cookie保留到的时间,以在自动登录时检查是否cookie是否过期
        //必须要生成数据摘要以防止cookie被篡改(如改holdTime),由于服务端可以由唯一用户名来得到用户密码,而密码明文传输不安全,
        //所以可以将密码,与要进行摘要的字段组合进行数据摘要,为了提高数据摘要破译的难度,可以在最后加一个只有服务端知道的固定值
        //生成数据摘要后要以文本传输,所以还要用Base64编码
        String value = name + "_" + holdTime + "_" + Base64.encode(MessageDigest.getInstance("md5").digest((password + ":" + holdTime + ":" + fixedValue).getBytes()));
        Cookie cookie = new Cookie("autoLogin", value);
        //设置cookie在客户端保留的时间,时间被篡改也没事,因为根本就不是这个时间决定到什么时候可以自动登录的
        cookie.setMaxAge(time);
        //设置cookie的访问域,域名以.开头(.google.com),表示该cookie对指定域名系统(DNS)区域中的服务器可见(例如www.google.com,但不是a.b.google.com)。默认情况下,Cookie只会返回给发送它们的服务器。
        //cookie.setDomain()由于测试时localhost非DNS域,这里不设置
        //设置cookie的路径,以/开头,默认是发送cookie的servlet的所在路径,这里设为根路径,域下的所有路径被访问时客户都会回传该cookie
        cookie.setPath("/");
        //设置是否只在https时请求时发该cookie,默认false
        cookie.setSecure(false);
        //设置cookie只能在http请求时发,HttpOnly Cookie不应该暴露给客户端脚本代码,因此可能有助于缓解某些类型的跨站点脚本攻击。
        cookie.setHttpOnly(true);
        //setComment()指定描述cookie用途的注释。如果浏览器向用户显示cookie就设置
        //setVersion()设置此Cookie的Cookie协议版本。默认为0,版本0符合最初的Netscape cookie规范,版本1符合RFC 2109。由于RFC 2109仍然太新,因此将版本1视为试验; 请勿在生产网站上使用它。
        return cookie;
    }

        3.在Filter中检测是否有该Cookie,及是否有效,有效就允许登录(保存用户到Session域中):

public class AutoLoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("user") != null) {
            chain.doFilter(request, response);
            return;
        }
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("autoLogin")) {
                    String value = cookie.getValue();
                    User user = valid(value);
                    if (user != null) {
                        request.getSession().setAttribute("user", user);
                    }
                    break;
                }
            }
        }
        chain.doFilter(request, response);
    }

    private User valid(String value) {
        try {
            String[] fields = value.split("\\_");
            User user = new UserDaoXmlImpl().findUser(fields[0]);
            String password = user.getPassword();
            String holdTime = fields[1];
            if (Long.valueOf(holdTime) < System.currentTimeMillis()) {
                return null;
            }
            String fixedValue = "hao";
            String md5 = Base64.encode(MessageDigest.getInstance("md5").digest((password + ":" + holdTime + ":" + fixedValue).getBytes()));
            if (fields[2].equals(md5)) {
                return user;
            }
        } catch (Exception e) {
            //这里正常是没有异常的,有的话表示有坏人改了cookie的值,如改为空则有空指针,数组越界
        }
        return null;
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}

        并在web.xml中配置该Filter:

    <filter>
        <description>自动登陆</description>
        <filter-name>autoLogin</filter-name>
        <filter-class>com.hao.web.filter.AutoLoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>autoLogin</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>

        4.如果用户要注销,则提示客户端把Cookie删除:

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getSession().setAttribute("user",null);
        //提示客户端把cookie删除
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                String name = cookie.getName();
                if (name.equals("autoLogin")){
                    Cookie autoLogin = new Cookie("autoLogin", "");
                    autoLogin.setMaxAge(0);
                    autoLogin.setPath("/");
                    response.addCookie(autoLogin);
                    break;
                }
            }
        }
        request.setAttribute("message","注销成功,三秒后自动跳到首页,没有跳转请点击<a href='/"+request.getContextPath()+"'>首页</a><meta http-equiv='refresh' content='3;url=/"+ request.getContextPath()+"'/>");
        request.getRequestDispatcher("/message.jsp").forward(request,response);
    }
that's all.






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值