验证-Tomcat来创建Filter实例,只会创建一个实例
package com.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* 1.filter在web项目启动时,由Tomcat来创建Filter实例,只会创建一个实例
* 2.会调用filter的默认无参构造器,同时会调用init()方法,只会调用一次
* 3.在创建filter实例时,同时会创建FilterConfig对象,并通过init()方法传入
* 4.通过FilterConfig对象,程序员可以获取该filter的相关配置信息
* 5.当一个http请求和该filter的url-pattern匹配时,就会调用doFilter()方法
* 6.在调用doFilter()方法时,Tomcat会同时创建ServletRequest,ServletResponse和FilterChain三个对象
* 并通过doFilter方法传入
* 7.如果后面的请求目标资源(jsp,servlet..)会使用到request,response,那么会继续传递,
* 即request和后面的request是同一个,response和后面的也是同一个
*/
public class ManageFilter implements Filter {
private int count = 0;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//当Tomcat创建filter后,会调用该方法,进行初始化
System.out.println("ManageFilter init方法被调用...");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain) throws IOException, ServletException {
System.out.println("doFilter被调用的次数=" + (++count));
}
@Override
public void destroy() {
//当filter对像被销毁时,就会调用该方法
System.out.println("ManageFilter destroy被调用...");
}
}
redeployTomcat,在浏览器访问资源,触发过滤器,后台输出如下:
FilterConfig接口图
FilterConfig说明
FilterConfig的简单使用:
DemoFilterConfig:
package com.filter;
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;
/**
* 演示FilterConfig使用
*/
public class DemoFilterConfig implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("DemoFilterConfig init方法被调用...");
//演示通过FilterConfig获取相关的参数
//获取filter在xml中配置的名字<filter-name>
String filterName = filterConfig.getFilterName();
//获取指定参数
String ip = filterConfig.getInitParameter("ip");
//filterConfig可以获取到ServletContext,
// 这意味着filter过滤器可以和任何Servlet进行通信
ServletContext servletContext = filterConfig.getServletContext();
//这里可以获取该filter所有的配置的参数名
// (也可以进一步使用getInitParameter获取指定参数)
Enumeration<String> initParameterNames =
filterConfig.getInitParameterNames();
//遍历枚举
while (initParameterNames.hasMoreElements()) {
System.out.println("名字= " + initParameterNames.nextElement());
}
System.out.println("filterName= " + filterName);
System.out.println("ip= " + ip);
System.out.println("servletContext= " + servletContext);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
}
}
在web.xml文件中配置filter:
<!--配置DemoFilterConfig-->
<filter>
<filter-name>DemoFilterConfig</filter-name>
<filter-class>com.filter.DemoFilterConfig</filter-class>
<!--这里就是给filter配置的参数-由程序员根据业务逻辑来设置-->
<init-param>
<param-name>ip</param-name>
<param-value>166.66.66.66</param-value>
</init-param>
<init-param>
<param-name>port</param-name>
<param-value>8888</param-value>
</init-param>
<init-param>
<param-name>email</param-name>
<param-value>jack@qq.com</param-value>
</init-param>
<!---->
</filter>
<filter-mapping>
<filter-name>DemoFilterConfig</filter-name>
<url-pattern>/abc/*</url-pattern>
</filter-mapping>
redeployTomcat,后台输出如下:
可以看到FilterConfig对象可以获取filter过滤器的配置内容。
需求:只要某个网段(如以127.0开头的ip)访问我们的web应用,就将其返回登录页面,不允许访问网站。
思路:在web.xml文件中,将要封杀的网段作为初始配置信息。filter实例创建的时候,在init方法中读取配置的要封杀的网段信息,在filter使用的过程中,如果发现用户的请求ip包含了配置的ip网段,就认为是被封杀的ip,进行处理。
细节补充:filter配置的初始化信息只能在init方法中通过FilterConfig对象来获取。为了让doFilter方法中也能使用到,我们在filter类中创建一个属性,在init方法中将获取的配置ip赋给属性,让其在doFilter方法中也能使用。
例子
DemoFilterConfig:
package com.filter;
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;
/**
* 演示FilterConfig使用
*/
public class DemoFilterConfig implements Filter {
private String ip;//从配置中获取的ip
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("DemoFilterConfig init方法被调用...");
//获取指定参数
ip = filterConfig.getInitParameter("ip");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
//通过forbidden ip来控制
//先获取访问ip
String remoteAddr = servletRequest.getRemoteAddr();
if (remoteAddr.contains(ip)) {//如果访问ip包含了配置ip
//封杀该网段
System.out.println("当前访问的ip为" + remoteAddr + "-封杀该网段...");
servletRequest.getRequestDispatcher("/login.jsp")
.forward(servletRequest, servletResponse);
return;//直接返回
}
//否则就继续访问目标资源
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
在web.xml中配置filter:
<!--配置DemoFilterConfig-->
<filter>
<filter-name>DemoFilterConfig</filter-name>
<filter-class>com.filter.DemoFilterConfig</filter-class>
<!--配置封杀网段-->
<init-param>
<param-name>ip</param-name>
<param-value>127.0</param-value>
</init-param>
<!---->
</filter>
<filter-mapping>
<filter-name>DemoFilterConfig</filter-name>
<url-pattern>/abc/*</url-pattern>
</filter-mapping>
redeployTomcat,在浏览器直接访问web应用abc目录下的资源,以触发filter。
可以看到浏览器直接返回登录页面。因为当前访问的ip为127.0.0.1,filter检测到当前地址为封杀网段,将页面直接转发回登录页面。
后台输出:
一句话FilterChain:在处理某些复杂业务时,一个过滤器不够,可以设计多个过滤器共同完成过滤任务,形成过滤器链。
如上,服务器接收请求,将请求中的url和过滤器的配置的url-pattern匹配,如果匹配成功,就会触发过滤器。如果匹配多个过滤器的url-pattern,则执行多个过滤器。
第一个过滤器调用doFilter方法,走前置代码(业务代码),运行到chain.doFilter()时,若请求的url符合其他过滤器配置的url-pattern,就会在doFilter方法中执行下一个filter过滤器的doFilter方法。
多个filter过滤器的执行顺序与web.xml文件中配置的顺序一致。
下一个filter过滤器执行完前置代码后,也在chain.doFilter()继续判断...依次类推,最后调用目标资源。
当目标资源调用完毕后,返回执行倒数第一个filter的后置代码(业务代码),然后返回执行倒数第二个filter后置代码,依次类推....直到第一个filter的后置代码执行完毕,然后服务器向浏览器返回响应。
这个返回调用的机制在事务提交上很有用
需求:演示过滤器链的使用
AFilter:
package com.filter;
import javax.servlet.*;
import java.io.IOException;
public class AFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("AFilter doFilter 的前置代码... ");
System.out.println("执行AFilter filterChain.doFilter()...");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("AFilter doFilter 的后置代码... ");
}
@Override
public void destroy() {
}
}
BFilter:
package com.filter;
import javax.servlet.*;
import java.io.IOException;
public class BFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("BFilter doFilter 的前置代码... ");
System.out.println("执行BFilter filterChain.doFilter()...");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("BFilter doFilter 的后置代码... ");
}
@Override
public void destroy() {
}
}
在admin目录下的hi.jsp:
<%--
Created by IntelliJ IDEA.
User: li
Date: 2022/11/29
Time: 17:55
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>admin 目录下的 hi.jsp</title>
</head>
<body>
<h1>admin 目录下的 hi.jsp</h1>
<h1>后台管理</h1>
<a href="#">用户列表</a>||<a href="#">添加用户</a>||<a href="#">删除用户</a>
<hr/>
</body>
</html>
在web.xml中配置filter:
<!--配置AFilter和BFilter-->
<filter>
<filter-name>AFilter</filter-name>
<filter-class>com.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>BFilter</filter-name>
<filter-class>com.filter.BFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
redeployTomcat,在浏览器访问http://localhost:8080/filter/admin/hi.jsp。
后台输出如下:
多个filter和目标资源在一次http请求中,在同一线程中
当一个请求url和filter的url-pattern匹配时,才会被执行,如果有多个匹配上,就会顺序执行,形成一个filter调用链
多个filter共同执行时,因为是一次http请求,使用的是同一个request对象
多个filter执行的顺序和web.xml配置顺序一致
chain.doFilter(req,resp)方法,将执行下一个过滤器的doFilter方法,如果后面没有过滤器,则执行目标资源
小结:注意执行过滤器链时,顺序是(以7.2的例子演示):
HTTP请求->A过滤器doFilter()->A过滤器前置代码->A过滤器chain.doFilter()->B过滤器doFilter()->B过滤器前置代码—>B过滤器chain.doFilter()->目标文件->B过滤器后置代码->A过滤器后置代码->返回给浏览器页面/数据
需求:使用过滤器,完成如下要求


练习
topic.jsp:
<%--
Created by IntelliJ IDEA.
User: li
Date: 2022/11/29
Time: 22:17
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>topic</title>
</head>
<body>
<form action="<%=request.getContextPath()%>/hw/showTopic.jsp" method="post">
<h1>发表对阿凡达电影的评论</h1>
过滤词:苹果,香蕉
<div style="color: red">${notice}</div>
用户:<input type="text" name="username"/><br/>
评论:<textarea cols="15" rows="5" name="topic"></textarea><br/>
<input type="submit" value="发表评论">
</form>
</body>
</html>
showTopic.jsp:
<%--
Created by IntelliJ IDEA.
User: li
Date: 2022/11/29
Time: 22:18
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>用户:<span style="color: #6799f3">
<%=request.getParameter("username")%></span></h3>
<h3>发表的评论是:<%=request.getParameter("topic")%>
</h3>
</body>
</html>
TopicFilter:
package com.filter.hw;
import javax.servlet.*;
import java.io.IOException;
public class TopicFilter implements Filter {
private String[] forbiddenWords;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//获取配置信息(禁用词)
String forbiddenWord = filterConfig.getInitParameter("forbiddenWord");
forbiddenWords = forbiddenWord.split(",");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
//注意中文乱码问题!!!
servletRequest.setCharacterEncoding("utf-8");
//获取用户评论
String username = servletRequest.getParameter("username");
String topic = servletRequest.getParameter("topic");
//评论不能为空
if (topic == null || "".equals(topic)) {
servletRequest.setAttribute("notice", "评论不能为空!");
servletRequest.getRequestDispatcher("/hw/topic.jsp")
.forward(servletRequest, servletResponse);
return;
}
//判断评论是否有禁用词
for (String forbiddenWord : forbiddenWords) {
if (topic.contains(forbiddenWord)) {
servletRequest.setAttribute("notice", "含有敏感词...");
servletRequest.getRequestDispatcher("/hw/topic.jsp")
.forward(servletRequest, servletResponse);
return;
}
}
//如果没有禁用词,且评论不为空
servletRequest.getRequestDispatcher("/hw/showTopic.jsp")
.forward(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
在web.xml中配置filter:
<!--配置TopicFilter-->
<filter>
<filter-name>TopicFilter</filter-name>
<filter-class>com.filter.hw.TopicFilter</filter-class>
<!--配置禁用词-->
<init-param>
<param-name>forbiddenWord</param-name>
<param-value>香蕉,苹果</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>TopicFilter</filter-name>
<!--精准匹配-->
<url-pattern>/hw/showTopic.jsp</url-pattern>
</filter-mapping>
redeployTomcat,在浏览器访问http://localhost:8080/filter/hw/topic.jsp
输入不含敏感词的评论:


输入含敏感词的评论:

是否有可能:before_filter:authenticate_user!||:authenticate_admin! 最佳答案 before_filter:do_authenticationdefdo_authenticationauthenticate_user!||authenticate_admin!end 关于ruby-on-rails-before_filter运行多个方法,我们在StackOverflow上找到一个类似的问题: https://
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json
1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析: 在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1: print(k)k=k/2A.1000 B.10C.11D.9解析: 按照题意每次循环K/2,直到K值小于等
我有一个名为Post的类,我需要能够适应以下场景:如果用户选择了一个类别,则只显示该类别的帖子如果用户选择了一种类型,则只显示该类型的帖子如果用户选择了一个类别和类型,则只显示该类别中该类型的帖子如果用户没有选择任何内容,则显示所有帖子我想知道我的Controller是否不可避免地会因大量条件语句而显得粗糙...这是我解决此问题的错误方法-有谁知道我如何才能做到这一点?classPostsController 最佳答案 您最好遵循“胖模型,瘦Controller”的惯例,这意味着您应该将这种逻辑放在模型本身中。Post类应该能够报告
我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?
我仍然收到标题中的“错误”消息,但不知道如何解决。在ApplicationController中,classApplicationController在routes.rb#match'set_activity_account/:id/:value'=>'users#account_activity',:as=>:set_activity_account--thisdoesn'tworkaswell..resources:usersdomemberdoget:action_a,:action_bendcollectiondoget'account_activity'endend和User
对于用户模型,我有一个过滤器来检查用户的预订状态,该状态由整数值(0、1或2)表示。UserActiveAdmin索引页上的过滤器是通过以下代码实现的:filter:booking_status,as::select然而,这会导致下拉选项为0、1或2。当管理员用户从下拉列表中选择它们时,我更愿意自己将它们命名为“未完成”、“待定”和“已确认”之类的名称。有没有办法在不改变booking_status在模型中的表示方式的情况下做到这一点? 最佳答案 假设booking_status是模型中的枚举字段,您可以使用:过滤器:booking
我有一个任务列表(名称、starts_at),我试图在每日View中显示它们(就像iCal)。deftodays_tasks(day)Task.find(:all,:conditions=>["starts_atbetween?and?",day.beginning,day.ending]end我不知道如何将Time.now(例如“2009-04-1210:00:00”)动态转换为一天的开始(和结束),以便进行比较。 最佳答案 deftodays_tasks(now=Time.now)Task.find(:all,:conditio
什么是0day漏洞?0day漏洞,是指已经被发现,但是还未被公开,同时官方还没有相关补丁的漏洞;通俗的讲,就是除了黑客,没人知道他的存在,其往往具有很大的突发性、破坏性、致命性。0day漏洞之所以称为0day,正是因为其补丁永远晚于攻击。所以攻击者利用0day漏洞攻击的成功率极高,往往可以达到目的并全身而退,而防守方却一无所知,只有在漏洞公布之后,才后知后觉,却为时已晚。“后知后觉、反应迟钝”就是当前安全防护面对0day攻击的真实写照!为了方便大家理解,中科三方为大家梳理当前安全防护模式下,一个漏洞从发现到解决的三个时间节点:T0:此时漏洞即0day漏洞,是已经被发现,还未被公开,官方还没有相