自动登录FilterSessionCookie综合例子.docx
《自动登录FilterSessionCookie综合例子.docx》由会员分享,可在线阅读,更多相关《自动登录FilterSessionCookie综合例子.docx(32页珍藏版)》请在冰豆网上搜索。
自动登录FilterSessionCookie综合例子
自动登录:
Filter,Session,Cookie综合例子
初始登录Servlet:
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
packagecn.xbai.servlet;
importjava.io.IOException;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassLoginSubmitServletextendsHttpServlet{
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
//response.getWriter().write("你好,小白!
");
//response.getWriter().write("
如果我没有乱码,就是使用了全局过滤器...
");
//防表单重复提交
//防盗链
//缓存
//...
//获取数据
Stringusername=request.getParameter("username");
Stringpassword=request.getParameter("password");
//数据合法性校验(放在业务层)
if(!
isEmpty(username)&&!
isEmpty(password)){
//response.getWriter().write("你好,小白!
");
}else{
if(isEmpty(username)){
//如果重定向放到Session里,就是扩大的域,再单独登录会取
//Session中的旧登录数据,这是错误的,而如果在登录UI的Servlet
//先清除Session又无法获取错误信息:
request.setAttribute("sorry1","用户名不能为空!
");
}
if(isEmpty(password)){
request.setAttribute("sorry2","密码不能为空!
");
}
//转发需要注意的就是这个UI页面form要用绝对URL地址,不然会错误,因为前后地址栏不同!
request.getRequestDispatcher("/servlet/LoginUIServlet").forward(request,response);
return;
}
}
privatebooleanisEmpty(Stringstr){
if(str==null||str.trim().equals("")){
returntrue;
}
returnfalse;
}
publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
doGet(request,response);
}
}
注意错误提示信息不能存放在Session,解释详见里面注释
UI页jsp:
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%>
DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
Jsp公子小白旗舰店
--发现如果这里用hr元素,下面的form就是报错,这种格式应该是非法,待查-->
登录名: | ${requestScope.sorry1} |
密码: | ${requestScope.sorry2} |
|
免费注册 |
加上过滤器,放行LoginUI和已登录用户:
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
packagecn.xbai.filter;
importjava.io.IOException;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importcn.xbai.domain.User;
publicclassAutoLoginFilterimplementsFilter{
publicvoiddestroy(){
//TODOAuto-generatedmethodstub
}
publicvoiddoFilter(ServletRequestreq,ServletResponseresp,
FilterChainchain)throwsIOException,ServletException{
//TODOAuto-generatedmethodstub
//应该排除掉登录UI的Servlet:
//如果不排除,由于没登录,访问登录页时会始终重复跳转登录页,处于永远无法登录状态
HttpServletRequestrequest=(HttpServletRequest)req;
HttpServletResponseresponse=(HttpServletResponse)resp;
Stringuri=request.getRequestURI();//从应用开始的部分地址
System.out.println(uri);
if(uri.contains("LoginUIServlet")){
System.out.println("LoginUI");
chain.doFilter(request,response);
}else{//不存在的访问地址留待其他机制去处理!
特定部件只管特定事情!
Useruser=(User)request.getSession().getAttribute("user");
if(user==null){
System.out.println("Notloggedin");
//检查带过来的Cookie,前提是上次登录设置了该Cookie
if(false){
}else{//没登录也没有上次登录时效信息
//jsp友好提示,并三秒重定向到登录UI
//response.sendRedirect(request.getContextPath()+"/servlet/LoginUIServlet");
request.getRequestDispatcher("/WEB-INF/jsp/redirect.jsp").forward(request,response);
}
}else{
//已登录,放行
chain.doFilter(request,response);
}
}
}
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
//TODOAuto-generatedmethodstub
}
}
过滤器跳转jsp:
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%>
DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
Jsp您还没有登录,亲!
(~_~)
效果:
进入登录页,直接点登录,会返回此页,因为跳转到的SubmitServlet同样处于未登录状态;输入不存在的url,显示404?
?
发现问题:
登录提交的Servlet也不该经过该过滤器!
否则也永远无法登录!
修改补全:
(同时经过了两个Filter,自动登录的Filter中,登录UI和Submit页面均放行,登录成功后访问另一个Servlet测试自动登录Filter的拦截)
此时访问不存在的地址会跳转到UI页面(第二个Filter拦截了,待研究调试?
?
)
未做:
登录时设置登录信息Cookie回写给浏览器
web.xml:
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
xmlversion="1.0"encoding="UTF-8"?
>
xmlns="
xmlns:
xsi="http:
//www.w3.org/2001/XMLSchema-instance"
xsi:
schemaLocation="
FilterDemo
cn.xbai.filter.FilterDemo
FilterDemo
/*
AutoLoginFilter
cn.xbai.filter.AutoLoginFilter
AutoLoginFilter
/*
FilterServlet
cn.xbai.servlet.FilterServlet
LoginUIServlet
cn.xbai.servlet.LoginUIServlet
LoginSubmitServlet
cn.xbai.servlet.LoginSubmitServlet
FilterServlet
/servlet/FilterServlet
LoginUIServlet
/servlet/LoginUIServlet
LoginSubmitServlet
/servlet/LoginSubmitServlet
index.jsp
第一个Filter:
防乱码Filter
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
packagecn.xbai.filter;
importjava.io.IOException;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importcn.xbai.request.FilterRequest;
publicclassFilterDemoimplementsFilter{
//为了获取config参数,这里定义一个来接收:
privateFilterConfigconfig;
//默认字符集
privateStringdefaultCharset="UTF-8";
//这里接收:
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
//TODOAuto-generatedmethodstub
this.config=filterConfig;
}
publicvoiddestroy(){
//TODOAuto-generatedmethodstub
}
//注意它的参数不是Http...类型,第一步需要先转成这种类型!
!
publicvoiddoFilter(ServletRequestreq,ServletResponseresp,
FilterChainchain)throwsIOException,ServletException{
System.out.println("Hi,Filter");
//TODOAuto-generatedmethodstub
//获取要设置的字符集------->不写死,写在filter配置中,这里获取
//设置缺省的,防止配置中未设置
Stringcharset=this.config.getInitParameter("charset");
if(charset==null){
charset=defaultCharset;
}
//知道服务器传递过来的是Http...这里先转成...
HttpServletRequestrequest=(HttpServletRequest)req;
HttpServletResponseresponse=(HttpServletResponse)resp;
request.setCharacterEncoding(charset);
//有时候只设置上面一行,因为mvc模式都是转给jsp输出,Servlet不用来输出,jsp页面已经设置了码表,所以不用在这里设置Servlet的response输出!
!
response.setCharacterEncoding(charset);
response.setContentType("text/html;charset="+charset);
//关于get乱码问题:
将request包装,修改getParameter方法
//然后这里将包装后的request传递过去:
chain.doFilter(newFilterRequest(request),response);
System.out.println("Hi,FilterReturn");
}
}
用到的Request包装类:
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
packagecn.xbai.request;
importjava.io.IOException;
importjava.io.UnsupportedEncodingException;
importjavax.servlet.ServletInputStream;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletRequestWrapper;
//继承Java提供的包装类,不用再复写所有Request该有的方法,只需复写自己需要的
publicclassFilterRequestextendsHttpServletRequestWrapper{
//源码跟踪:
该类最顶级基类中定义了一个ServletRequest
//而不是HttpServletRequest,名为request,是被包装对象,
//可以传给它HttpServletRequest进行初始化,但要用到
//HttpServletRequest全部功能需要强转(多态)
/**
*并且该ServletRequest是基类私有,无法在子类调用,所以重新定义,并重写构造方法:
*/
privateHttpServletRequestrequest;
publicFilterRequest(HttpServletRequestrequest){
//经测:
父类也必须初始化,无论是否利用:
//除了下面构造函数的原因,经源码跟踪,最重要的:
父类根据传入的request获取到它后
//强转成HttpServletRequest,调用其每个方法实现包装类,如果不传,那么
//HttpServletRequest的方法根本就无法实现,那么就不是包装类
//注意这些实现的方法是HttpServletRequest的方法
//getParameter方法重写:
HttpServletRequest是接口类型,调用Web容器传递过来的
//实现类对象的该方法实现修改
/**
*ImplicitsuperconstructorHttpServletRequestWrapper()
*isundefined.Mustexplicitlyinvokeanotherconstructor
*/