有关JavaEE中filter的一些应用场景

         Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、用户自动登录,解决全站乱码,过滤敏感词汇、压缩响应信息等一些高级功能。(注意,fikter中配置属性<dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截。)

        filter在开发中的常见应用:
     * 1.filter可以目标资源执行之前,进行权限检查,检查用户有无权限,如有权限则放行,如没有,则拒绝访问
     * 2.filter可以放行之前,对request和response进行预处理,从而实现一些全局性的设置。
     * 3.filter在放行之后,可以捕获到目标资源的输出,从而对输出作出类似于压缩这样的设置

        一,解决全网站的乱码:

	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		
		request.setCharacterEncoding("UTF-8");  //这个编码只能解决Post提交,不能解决get方式的提交,所以需要对request中getParameter
		                                       //方法增强
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		
		chain.doFilter(new MyRequest(request), response);   //request.getparameter("password");
	}
	
	/*
	1.写一个类,实现与被增强对象相同的接口
	2.定义一个变量,记住被增强对象
	3.定义一个构造方法,接收被增强对象
	4.覆盖想增强的方法
	5.对于不想增强的方法,直接调用被增强对象(目标对象)的方法
	 */
	
	class MyRequest extends HttpServletRequestWrapper{

		private HttpServletRequest request;
		public MyRequest(HttpServletRequest request) {
			super(request);
			this.request = request;
		}
		@Override
		public String getParameter(String name) {
			
			String value = this.request.getParameter(name);
			if(!request.getMethod().equalsIgnoreCase("get")){
				return value;
			}
			
			if(value==null){
				return null;
			}
			
			try {
				return value = new String(value.getBytes("iso8859-1"),request.getCharacterEncoding());
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e);
			}
			
		}
		
		}
          二,实现自动登录

        实现用户自动登陆的过滤器
       在用户登陆成功后,发送一个名称为user的cookie给客户端,cookie的值为用户名和md5加密后的密码。编写一个AutoLoginFilter,这个filter检查用户是否带有名称为user的cookie来,如果有,则调用dao查询cookie的用户名和密码是否和数据库匹配,匹配则向session中存入user对象(即用户登陆标记),以实现程序完成自动登陆。

public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		 
		
		
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		
		//1.先检查用户是否已登陆,没登陆才自动登陆
		User user = (User) request.getSession().getAttribute("user");
		
		if(user!=null){
			chain.doFilter(request, response);
			return;
		}
		
		//2.没登陆,再执行自动登陆逻辑
		
		//看用户有没有带自动登陆的cookie
		Cookie autoLoginCookie = null;
		Cookie cookies[] = request.getCookies();
		
		for(int i=0;cookies!=null && i<cookies.length;i++){
			if(cookies[i].getName().equals("autologin")){
				autoLoginCookie = cookies[i];
			}
		}
		if(autoLoginCookie==null){
			chain.doFilter(request, response);
			return;
		}
		
		//用户带了自动登陆的cookie,则先检查cookie的有效期 
		String values[] = autoLoginCookie.getValue().split("\\:");
		if(values.length!=3){
			chain.doFilter(request, response);
			return;
		}
		long expirestime = Long.parseLong(values[1]);
		if(System.currentTimeMillis()>expirestime){
			chain.doFilter(request, response);
			return;
		}
	
		//代表cookie时间有效,再检查cookie的有效性
		String username = values[0];
		String client_md5 = values[2];
		
		BusinessService service = new BusinessService();
		user = service.findUser(username);
		if(user==null){
			chain.doFilter(request, response);
			return;
		}
		autologin=username:expirestime:md5(password:expirestime:username)
		String server_md5 = md5(user.getUsername(),user.getPassword(),expirestime);
		if(!server_md5.equals(client_md5)){
			chain.doFilter(request, response);
			return;
		}
		
		//执行登陆
		request.getSession().setAttribute("user", user);
		chain.doFilter(request, response);
		
	}
	
	private String md5(String username,String password,long expirestime){
		
		try{
			String value = password + ":" + expirestime + ":" + username;
			MessageDigest md = MessageDigest.getInstance("md5");
			byte md5[] = md.digest(value.getBytes());
			BASE64Encoder encode = new BASE64Encoder();
			return encode.encode(md5);
		}catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String username = request.getParameter("username");
		String password = request.getParameter("password");
		
		BusinessService service = new BusinessService();
		User user = service.login(username, password);
		if(user==null){
			request.setAttribute("message", "用户名或密码错误!!");
			request.getRequestDispatcher("/message.jsp").forward(request, response);
			return;
		}
		
		request.getSession().setAttribute("user", user);
		int expirestime = Integer.parseInt(request.getParameter("time"));
		//给客户机发送自动登陆的 cookie  
		//autologin=username:expirestime:md5(password:expirestime:username)
		Cookie cookie = makeCookie(user, expirestime);
		response.addCookie(cookie);
		response.sendRedirect("/login/index.jsp");
	}
	
	public Cookie makeCookie(User user,int expirestime){
		long currenttime = System.currentTimeMillis();
		String cookieValue = user.getUsername() + ":" + (currenttime+expirestime*1000) + ":" + md5(user.getUsername(), user.getPassword(), (currenttime+expirestime*1000));
		Cookie cookie = new Cookie("autologin",cookieValue);
		cookie.setMaxAge(expirestime);
		cookie.setPath("/login");
		return cookie;
	}
	
	private String md5(String username,String password,long expirestime){
		
		try{
			String value = password + ":" + expirestime + ":" + username;
			MessageDigest md = MessageDigest.getInstance("md5");
			byte md5[] = md.digest(value.getBytes());
			BASE64Encoder encode = new BASE64Encoder();
			return encode.encode(md5);
		}catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

 三,禁止浏览器缓存所有动态页面的过滤器:
        有 3 个 HTTP 响应头字段都可以禁止浏览器缓存当前页面,它们在 Servlet 中的示例代码如下:
             response.setDateHeader("Expires",-1);
             response.setHeader("Cache-Control","no-cache");
             response.setHeader("Pragma","no-cache");
       并不是所有的浏览器都能完全支持上面的三个响应头,因此最好是同时使用上面的三个响应头。
             Expires数据头:值为GMT时间值,为-1指浏览器不要缓存页面
             Cache-Control响应头有两个常用值:
             no-cache指浏览器不要缓存当前页面。
             max-age:xxx指浏览器缓存页面xxx秒。

四,控制浏览器缓存页面中的静态资源的过滤器:
        有些动态页面中引用了一些图片或css文件以修饰页面效果,这些图片和css文件经常是不变化的,所以为减轻服务器的压力,可以使用filter控制浏览器缓存这些文件,以提升服务器的性能。
private Map<String,byte[]> map = new HashMap();
	
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		
		//1.得到用户想访问的资源(uri)
		String uri = request.getRequestURI();
		
		//2.看map集合中是否保存了该资源的数据
		byte b[] = map.get(uri);
		
		//3.如果保存了,则直接取数据打给浏览器
		if(b!=null){
			response.getOutputStream().write(b);
			return;
		}
		
		//4.如果没有保存数据,则放行让目标资源执行,这时还需写一个response的包装类,捕获目标资源的输出
		MyResponse my = new MyResponse(response);
		chain.doFilter(request, my);
		byte data[] = my.getBuffer();
		
		//5.以资源uri为关键字,打资源的数据保存map集合中,以备于下次访问
		map.put(uri, data);
		
		//6.输出数据给浏览器
		response.getOutputStream().write(data);
		
		

	}
	
	class MyResponse extends HttpServletResponseWrapper{
		private ByteArrayOutputStream bout = new ByteArrayOutputStream();
		private PrintWriter pw;
		
		private HttpServletResponse response;
		public MyResponse(HttpServletResponse response) {
			super(response);
			this.response = response;
		}
		@Override
		public ServletOutputStream getOutputStream() throws IOException {
			return new MyServletOutputStream(bout);    //myresponse.getOutputStream().write("hahah");
		}
		
		@Override
		public PrintWriter getWriter() throws IOException {
			pw = new PrintWriter(new OutputStreamWriter(bout,response.getCharacterEncoding()));
			return pw;  
		}
		public byte[] getBuffer(){
			if(pw!=null){
				pw.close();
			}
			return bout.toByteArray();
		}
	}
	
	class MyServletOutputStream extends ServletOutputStream{

		private ByteArrayOutputStream bout;
		public MyServletOutputStream(ByteArrayOutputStream bout){
			this.bout = bout;
		}
		@Override
		public void write(int b) throws IOException {
			bout.write(b);
		}
		
	}

、使用Decorator模式包装request对象,实现html标签转义功能(Tomcat服务器中提供了转义html标签的工具类)

public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		
		chain.doFilter(new MyRequest(request), response);  //request.getParameter("resume");  //<script>
		

	}
	
	class MyRequest extends HttpServletRequestWrapper{
		private HttpServletRequest request;
		public MyRequest(HttpServletRequest request) {
			super(request);
			this.request = request;
		}
		@Override
		public String getParameter(String name) {
			
			String value = this.request.getParameter(name);
			if(value==null){
				return null;
			}
			return filter(value);
		}
		
		public String filter(String message) {

	        if (message == null)
	            return (null);

	        char content[] = new char[message.length()];
	        message.getChars(0, message.length(), content, 0);
	        StringBuffer result = new StringBuffer(content.length + 50);
	        for (int i = 0; i < content.length; i++) {
	            switch (content[i]) {
	            case '<':
	                result.append("<");
	                break;
	            case '>':
	                result.append(">");
	                break;
	            case '&':
	                result.append("&");
	                break;
	            case '"':
	                result.append(""");
	                break;
	            default:
	                result.append(content[i]);
	            }
	        }
	        return (result.toString());

	    }
}
六、 压缩响应信息

      服务器发给浏览器的数据时,先进行压缩,然后在发出,(注意filter要拦截的对象,都会压缩,所以要在web.xml中配置好想要拦截的对象)。

public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		MyResponse myresponse = new MyResponse(response);
		
		
		chain.doFilter(request, myresponse);  //response.getwriter  response.getOutputStream  
		
		//取出缓冲的数据压缩后输出
		byte out[] = myresponse.getBuffer();  //得到目标资源的输出
		byte gzipout[] = gzip(out);
		response.setHeader("content-encoding", "gzip");
		response.setHeader("content-length", gzipout.length + "");
		response.getOutputStream().write(gzipout);
	}
	
	public byte[] gzip(byte b[]) throws IOException{
		
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		GZIPOutputStream gout = new GZIPOutputStream(bout);
		gout.write(b);
		gout.close();
		return bout.toByteArray();
	}
	
	class MyResponse extends HttpServletResponseWrapper{
		private ByteArrayOutputStream bout = new ByteArrayOutputStream();
		private PrintWriter pw;
		
		private HttpServletResponse response;
		public MyResponse(HttpServletResponse response) {
			super(response);
			this.response = response;
		}
		@Override
		public ServletOutputStream getOutputStream() throws IOException {
			return new MyServletOutputStream(bout);    //myresponse.getOutputStream().write("hahah");
		}
		
		@Override
		public PrintWriter getWriter() throws IOException {
			pw = new PrintWriter(new OutputStreamWriter(bout,response.getCharacterEncoding()));
			return pw;  
		}
		public byte[] getBuffer(){
			if(pw!=null){
				pw.close();
			}
			return bout.toByteArray();
		}
	}
	
	class MyServletOutputStream extends ServletOutputStream{

		private ByteArrayOutputStream bout;
		public MyServletOutputStream(ByteArrayOutputStream bout){
			this.bout = bout;
		}
		@Override
		public void write(int b) throws IOException {
			bout.write(b);
		}
		
	}
七。敏感词过滤(z注意词库中词语的格式:例如:傻逼|1   后面的1表示识别词库中的等级 ,禁用词为1,审查词为2,替换词为3 )

private List<String> banWords = new ArrayList();//禁用词,例如:傻逼|1  
	private List<String> auditWords = new ArrayList();//审查词   例如: 中共|2
	private List<String> replaceWords = new ArrayList();//替换词  例如: 色情|3
	
	public void init(FilterConfig filterConfig) throws ServletException {
		try{
			String path = WordsFilter.class.getClassLoader().getResource("cn/xxx/xxx").getPath();//地址表词库存放在那个包下面
			File files[] =  new File(path).listFiles();
			for(File file : files){
				if(!file.getName().endsWith(".txt")){//表示词库的后缀名文件
					continue;
				}
				BufferedReader br = new BufferedReader(new FileReader(file));
				String line = null;
				while((line=br.readLine())!=null){
					String s[] = line.split("\\|");
					if(s.length!=2){
						continue;
					}
					if(s[1].trim().equals("1")){
						banWords.add(s[0].trim());
					}
					
					if(s[1].trim().equals("2")){
						auditWords.add(s[0].trim());
					}
					
					if(s[1].trim().equals("3")){
						replaceWords.add(s[0].trim());
					}
				}
			}
			System.out.println("haha");
		}catch (Exception e) {
			throw new RuntimeException(e);
		}

	}
	
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		
		//检查提交数据是否包含禁用词
		Enumeration e = request.getParameterNames();
		while(e.hasMoreElements()){
			String name = (String) e.nextElement();
			String data = request.getParameter(name); 
			for(String regex : banWords){
				Pattern pattern = Pattern.compile(regex);
				Matcher m = pattern.matcher(data);
				if(m.find()){
					request.setAttribute("message", "文章中包括非法词汇,请检查后再提交!!");
					request.getRequestDispatcher("/message.jsp").forward(request, response);
					return;
				}
			}
		}
		
		//检查审核词
		
		//检查替换词
		chain.doFilter(new MyRequest(request), response);
		
	}
	
	
	class MyRequest extends HttpServletRequestWrapper{
		private HttpServletRequest request;
		public MyRequest(HttpServletRequest request) {
			super(request);
			this.request = request;
		}
		@Override
		public String getParameter(String name) {
			
			String data = this.request.getParameter(name);
			if(data==null){
				return null;
			}
			for(String regex : auditWords){//检查审核词
				Pattern p = Pattern.compile(regex);
				Matcher m = p.matcher(data);
				if(m.find()){    
					String value = m.group();  //找出客户机提交的数据中和正则表达式相匹配的数据
					data = data.replaceAll(regex, "<font color='red'>" + value + "</font>");
				}
			}
			
			
			for(String regex : replaceWords){//检查替换词
				Pattern p = Pattern.compile(regex);
				Matcher m = p.matcher(data);
				if(m.find()){   
					data = data.replaceAll(regex, "*******");
				}
			}
			
			return data;
		}
	}
	


                                                     

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值