使用filter过滤请求
来源:互联网 发布:mac 全角半角 编辑:程序博客网 时间:2024/06/08 15:57
使用filter过滤请求
Filter虽然很常用,但是覆盖的范围太广,这里我们只介绍设置编码和控制权限的过滤器,其他的使用方式还需要大家自行积累。
如果你不满足以下任一条件,请继续阅读,否则请跳过此后的部分,进入下一章:第 8 章 配置listener监听器。 - 了解Filter的使用。
7.2. 用filter控制用户访问权限
现在用户还没有登录,如果直接访问保密信息,就会显示无法访问保密信息的页面,并提醒用户进行注册。
返回登录页面后,输入正确的用户名和密码,点击登录。
后台程序判断用户名和密码正确无误后,在session中设置已登录的标记,然后跳转到保密信息页面。
我们要保护的页面是admin/index.jsp,为此我们在web.xml进行如下配置。
<filter> <filter-name>SecurityFilter</filter-name> <filter-class>anni.SecurityFilter</filter-class> </filter> <filter-mapping> <filter-name>SecurityFilter</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping>
定义SecurityFilter过滤器,让它过滤匹配/admin/*的所有请求,这就是说,对/admin/路径下的所有请求都会接受SecurityFilter的检查,那么SecurityFilter里到底做了些什么呢? public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; HttpSession session = req.getSession(); if (session.getAttribute("username") != null) { chain.doFilter(request, response); } else { res.sendRedirect("../failure.jsp"); } }
首先要将ServletRequest和ServletResponse转换成HttpServletRequest和HttpServletResponse,因为Filter本来设计成为多种协议服务,http协议仅仅是其中一部分。不过我们接触到的也只有http,而且也只有转换成对应HttpServletRequest和HttpServletResponse才能进行下面的session操作和页面重定向。得到了http请求之后,可以获得请求对应的session,判断session中的username变量是否为null,如果不为null,说明用户已经登录,就可以调用doFilter继续请求访问的资源。如果为null,说明用户还没有登录,禁止用户访问,并使用页面重定向跳转到failure.jsp页面显示提示信息。 session中的username实在登录的时候设置进去的,值就是登录用户使用的用户名,详细代码可以参考07-02/WEB-INF/src/LoginServlet.java,登录和注销都写成了servlet并映射到/login.do和/logout.do这两个请求路径上。源代码和web.xml配置请自行参考07-02中的例子,这里就不复述了。我们再来看看页面重定向的写法,res.sendRedirect()中使用的是"../failure.jsp",两个点(..)代表当前路径的上一级路径,这是因为SecurityFilter负责处理的是/admin/下的请求,而/failure.jsp的位置在/admin/目录的上一级,所以加上两个点才能正确跳转到failure.jsp。当然这里使用forward()也可以,但是要注意在不同路径下做请求转发会影响页面中相对路径的指向。相关讨论在:第 3.4.2 节 “forward导致找不到图片”。7.3. filter所谓的特性
7.3.1. 请求映射
- 直接映射一个请求。
<servlet-mapping> <servlet-name>ContactServlet</servlet-name> <url-pattern>/contact.do</url-pattern> </servlet-mapping>
像第 6.3 节 “使用servlet改写联系簿”中对servlet的映射,只有当请求是/contact.do的时候才会执行ContactServlet。/contact.do?id=1或/contact.do?method=list&id=1的请求也可以匹配到ContactServlet,这是因为根据http规范,请求的路径不包含问号以后的部分。 - 映射一个路径下的所有请求。
<servlet-mapping> <servlet-name>EncodingFilter</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
像第 7.1 节 “批量设置请求编码”中这样使用星号(*)的形式,可以将某个路径下的所有请求都映射到EncodingFilter过滤器下,如果这个路径下还有子路径,那么子路径下的请求也会被EncodingFilter过滤。所以 /*这种写法就会过滤应用下所有的请求。 如果像第 7.2 节 “用filter控制用户访问权限”中那样把映射配置成/admin/*,就会只处理/admin/路径下的请求,不会处理根路径下的/index.jsp和/failure.jsp。需要注意的是,这种写法必须以/开头,写成与绝对路径的形式,即便是映射所有请求也要写成/*,不能简化成*。 - 映射结尾相同的一类请求。
<servlet-mapping> <servlet-name>ControllerServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
具体效果请参考07-03的例子,index.jsp中有四个链接,分别指向/a1.do, /a2.do, /xx/b1.do, /xx/yy/c1.do。web.xml中的ControllerServlet会接收以.do结尾的请求,并使用forward将请求转发到/test.jsp。点击/a1.do的情况。点击/xx/yy/c1.do的情况。这样做的一个好处是语义更清楚,只要看到以.do结尾的请求就知道肯定是交给ControllerServlet处理了,不管这个请求是在根路径还是子路径下,都会准确无误的找到对应的servlet。缺点就是不同路径之间进行forward,jsp里就不能再使用相对路径了,所以我们在test.jsp中使用request.getContextPath()获得当前应用在服务器中的位置(例子中是/07-03)将相对路径都组装成绝对路径,这种用法在以后也会经常用到。<% pageContext.setAttribute("ctx", request.getContextPath()); %> <p><a href="${ctx}/index.jsp">返回</a></p>
最后需要注意的是,这种请求映射就不能指定某一路径了,它必须是以星号(*)开始字母结尾,不能写成/*.do的形式。
<servlet-mapping> <servlet-name>ControllerServlet</servlet-name> <url-pattern>/user/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ControllerServlet</servlet-name> <url-pattern>/admin/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ControllerServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
java的复杂性在此处显露无疑。实际使用时,最好不要依赖web.xml中的配置,在自己的类中实现灵活配置才是正途。7.3.2. 过滤链
所有的奥秘就在Filter中的FilterChain中。服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法。执行的顺序就如上图所示,执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的chain.doFilter()之后的代码,最后返回响应。因此在07-02中执行的代码顺序是:
- 执行EncodingFilter.doFilter()中chain.doFilter()之前的部分:request.setCharacterEncoding("gb2312");
- 执行SecurityFilter.doFilter()中chain.doFilter()之前的部分:判断用户是否已登录。如果用户已登录,则访问请求的资源:/admin/index.jsp。如果用户未登录,则页面重定向到:/failure.jsp。
- 执行SecurityFilter.doFilter()中chain.doFilter()之后的部分:这里没有代码。
- 执行EncodingFilter.doFilter()中chain.doFilter()之后的部分:这里也没有代码。
7.4. filter的详细配置
<filter> <filter-name>TestFilter</filtername> <filter-class>anni.TestFilter</filter-class> </filter> <filter-mapping> <filter-name>TestFilter</filtername> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>EXCEPTION</dispatcher> </filter-mapping>
这样TestFilter就会过滤所有状态下的请求。如果我们没有进行设置,默认使用的就是REQUEST。而EXCEPTION是在isErrorPage="true"的情况下出现的,这个用处不多,看一下即可。这里FORWARD是解决request.getDispatcher("index.jsp").forward(request, response);无法触发Filter的关键,配置上这个以后再进行forward的时候就可以触发过滤器了。 Filter还有一个有趣的用法,在filter-mapping中我们可以直接指定servlet-mapping,让过滤器只处理一个定义在web.xml中的servlet。 <filter-mapping> <filter-name>TestFilter</filter-name> <servlet-name>TestServlet</servlet-name> </filter-mapping> <servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>anni.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet</servlet-name> <url-pattern>/TestServlet</url-pattern> </servlet-mapping>
直接指定servlet-name,TestFilter便会引用TestServlet配置的url-pattern,在某些filter与servlet绑定的情况下不失为一个好办法。- 使用filter过滤请求
- 使用filter过滤请求
- 使用filter过滤请求
- Filter过滤器 过滤请求
- Druid filter过滤请求
- Servlet中使用Filter来过滤请求编码
- Filter过滤器的使用,实现在规定时间内过滤请求
- 使用struts2时,filter过滤器只过滤jsp文件不过滤action请求
- 使用struts2时,filter过滤器只过滤jsp文件不过滤action请求 .
- SpringBoot设置Filter过滤请求参数
- fiddler filters 使用(fiddler只显示指定请求,fiddler不显示指定请求,即filter请求过滤)
- fiddler filters 使用(fiddler只显示指定请求,fiddler不显示指定请求,即filter请求过滤)
- Lucene使用Filter搜索过滤
- 使用filter过滤xss攻击
- 使用filter过滤xss攻击
- 使用filter过滤特定资源
- 使用filter过滤xss攻击
- 使用filter过滤xss攻击
- 在指定路径中查找指定字符串
- 通过鼠标事件来看QT/Embedded 窗体事件是如何派发的
- SQL Server 2000中的数据同步问题
- 安装firebug进行调试
- aspnet+iis随意修改网页后缀名!
- 使用filter过滤请求
- Qt的鼠标和触摸屏驱动
- excel中如何输入身份证号
- Linux 杂记(一)
- 一个方便有用的Delphi数据库操作类(转)
- 该如何加载google-analytics(或其他第三方)的JS (转自http://www.cnblogs.com/BearsTaR/archive/2010/05/12/best_use_google_analytics.html)
- 支持UCenter的PHP建站程序一览
- 噬石真象
- 当 xml中存在命名空间,三种处理办法(dom4j)