大数据正式21

来源:互联网 发布:网络防御技术 编辑:程序博客网 时间:2024/06/05 10:45

大数据正式21

过滤器

  • 定义
    1. Filter--过滤器
    2. 是Servlet中最实用的技术--JavaEE核心技术之一【Servlet+Filter+Listener】
    3. 可以拦截对资源的访问,拦截下来后可以是否允许通过时,在之前或之后做一些额外单位操作,所谓的拦截,其实是将代表请求的request对象和代表Response对象拦截下来;责任链模式【依次拦截、检查、和控制】
    4. 一个资源看可以被多个过滤器拦截
    5. 一个拦截器也可以拦截多个资源
  • 图解
  • 常见使用场景
    • 基于URL的访问控制权限
    • 全站乱码解决过滤器
    • 自动登录
    • 过滤敏感词
    • 压缩响应
    • 。。。
  • 实现一个过滤器的步骤

    1. 写一个类实现Filter接口

      1. public void init(FilterConfig arg0) throws ServletException
        • 初始化方法
      2. public void doFilter(final ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException, ServletException
        • 最核心的方法,在存活期间,会造成此方法的执行,在里面写逻辑代码即可
      3. public void destroy()
        • 在过滤器被销毁之前调用,实现善后操作
      4. api
      5. package com.peng.filter;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class FilterDemo implements Filter {    public void destroy() {        System.out.println("destory");    }    public void doFilter(ServletRequest arg0, ServletResponse arg1,            FilterChain arg2) throws IOException, ServletException {        System.out.println("kernel");    }    public void init(FilterConfig arg0) throws ServletException {        System.out.println("init");    }}
    2. 在web.xml中配置过滤器

      <!-- 过滤器 --><filter>    <filter-name>FilterDemo</filter-name>    <filter-class>com.peng.filter.FilterDemo</filter-class></filter><filter-mapping>    <filter-name>FilterDemo</filter-name>    <url-pattern>/*</url-pattern></filter-mapping>
  • filter的生命周期
    • 在web应用启动的时候,会创建出应用中配置的过滤器对象,init方法进行初始化操作,之后一直存活,直到web应用销毁时,Filter跟着被销毁,再销毁之前执行destory方法的逻辑。在存活期间,进行对资源的拦截处理(doFilter方法),可以增加before和after方法,进行处理,一层一层进,一层一层出。
    • 调用过程
      • 如果一个资源被多个过滤器拦截,顺序为【mapping】配置的顺序
  • 和Filter相关的对象
    • FilterConfig过滤器配置对象
      1. init方法的参数
      2. 获取filter初始化参数
      3. 获取ServletContext对象
      4. 例子

        <filter>    <filter-name>FilterDemo</filter-name>    <filter-class>com.peng.filter.FilterDemo</filter-class>    <init-param>        <param-name>key1</param-name>        <param-value>value1</param-value>    </init-param>    <init-param>        <param-name>key2</param-name>        <param-value>value2</param-value>    </init-param></filter>

        public void init(FilterConfig arg0) throws ServletException {    System.out.println("init");    Enumeration initParameterNames = arg0.getInitParameterNames();    while (initParameterNames.hasMoreElements()) {        String name = initParameterNames.nextElement().toString();        System.out.println(name + "~" + arg0.getInitParameter(name));    }}
        • 执行效果
    • FilterChain
      1. doFilter函数的参数
      2. 代表过滤器链
      3. 提供doFilter方法,执行之后的过滤器

        public void doFilter(final ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException, ServletException {    // 过滤具体操作    // 释放资源--责任链模式,进行下一个过滤器执行操作    arg2.doFilter(arg0, arg1);}

Filter应用

  • 全站乱码解决过滤器

    • 请求乱码

      • GET方式

        1. 解决方案一:获取参数,解决乱码,再放回去
          • 有问题:Request方法没setParameter方法
        2. 解决方案二:request中的数据包无法改变,只能改变其原始方法

          1. 继承【这里不能使用】:对已有对象的改造无效--因为对象是已经生成的,不能new出新的子类对象
          2. 可以使用装饰模式装饰request方法【这里能使用】:

            • getParameter(String key)
            • getParameterValues()
            • getParameterMap

              package com.easymall.filter;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.util.Map;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;public class EncodingFilter implements Filter {    private String encode = null;    // 初始化过滤器    public void init(FilterConfig arg0) throws ServletException {        // 获取ServletContext对象        ServletContext sc = arg0.getServletContext();        // 获取全局变量之编码        this.encode = sc.getInitParameter("encode");    }    public void doFilter(final ServletRequest arg0, ServletResponse arg1,            FilterChain arg2) throws IOException, ServletException {        // 请求乱码-get、post一起解决        MyServletRequest msr = new MyServletRequest((HttpServletRequest) arg0);        // 响应乱码        arg1.setCharacterEncoding(encode);        arg1.setContentType("text/html;charset=" + encode);        // 释放资源        arg2.doFilter(msr, arg1);    }    // 销毁过滤器方法    public void destroy() {    }    // 内部类装饰    class MyServletRequest extends HttpServletRequestWrapper {        private ServletRequest request = null;        private boolean hasNoteEncode = true;        public MyServletRequest(HttpServletRequest request) {            super(request);            this.request = request;        }        // 改造方法        @Override        public String getParameter(String name) {            return this.getParameterValues(name) == null ? null : this                    .getParameterValues(name)[0];        }        // 改造方法        @Override        public Map<String, String[]> getParameterMap() {            try {                // 注:第一次map之后就对了,得处理--加一个标记                @SuppressWarnings("unchecked")                Map<String, String[]> map = request.getParameterMap();                if (hasNoteEncode) {                    for (Map.Entry<String, String[]> entry : map.entrySet()) {                        String[] values = entry.getValue();                        for (int i = 0; i < values.length; i++) {                            values[i] = new String(                                    values[i].getBytes("iso8859-1"), encode);                        }                    }                    hasNoteEncode = false;                }                return map;            } catch (UnsupportedEncodingException e) {                e.printStackTrace();                throw new RuntimeException(e);            }        }        // 改造方法        @Override        public String[] getParameterValues(String name) {            return this.getParameterMap().get(name);        }    }}
          3. 动态代理:通过代理对象来改造,并且通过代理对象访问被代理对象【这里能使用】:

            package com.easymall.filter;import java.io.IOException;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;public class EncodingFilter implements Filter {    private String encode = null;    public void destroy() {    }    public void doFilter(final ServletRequest arg0, ServletResponse arg1,            FilterChain arg2) throws IOException, ServletException {        // 请求乱码-get-- 动态代理        // 将ServletRequest强转为HttpServletRequest        final HttpServletRequest hsr = (HttpServletRequest) arg0;        // get转码---动态代理方法        // 2、创建代理对象【固定】        // 参数一:被代理对象的类加载器。 实现方式:被代理对象.getClass().getClassLoader()        // 参数二:被代理对象的接口数组。 实现方式:被代理对象.getClass().getInterfaces()        // 参数三:处理类【用来增强方法的】        // 增强代码需要写在处理类的 invoke方法中即可        HttpServletRequest obj = (HttpServletRequest) Proxy.newProxyInstance(                hsr.getClass().getClassLoader(), // 获取被代理类类加载器                hsr.getClass().getInterfaces(), // 获取被代理类实现类的接口                new InvocationHandler() {                    // 参数一: Object proxy 代理对象。没用                    // 参数二: Method method 被代理对象的对应方法                    // 参数三: Object[] args 被代理对象对应方法执行时,传递的实参                    public Object invoke(Object arg0, Method method,                            Object[] arg2) throws Throwable {                        // 针对getParameter方法进行增强                        if ("getParameter".equals(method.getName())) {                            // 获取提交方式                            String m = hsr.getMethod();                            if ("GET".equalsIgnoreCase(m)) {                                // 调用原来的方法                                String invoke = (String) method.invoke(hsr,                                        arg2);                                String re = null;                                try {                                    // 转码                                    re = new String(invoke                                            .getBytes("iso8859-1"), encode);                                } catch (Exception e) {                                }                                return re;                            }                        }                        return method.invoke(hsr, arg2);                    }                });        // 请求乱码-post        arg0.setCharacterEncoding(encode);        // 响应乱码        arg1.setCharacterEncoding(encode);        arg1.setContentType("text/html;charset=" + encode);        // 释放资源        arg2.doFilter(obj, arg1);    }    public void init(FilterConfig arg0) throws ServletException {        ServletContext sc = arg0.getServletContext();        this.encode = sc.getInitParameter("encode");    }}
      • POST方式

        arg0.setCharacterEncoding(encode);
    • 响应乱码
      • 解决方案

        arg1.setCharacterEncoding(encode);arg1.setContentType("text/html;charset=" + encode);

自动登录

  • 不加过滤器的登录
  • 加入过滤器的登录
  • 在处理用户登录时
    1. 首次登录时:判断是否勾选过自动登录
      1. 否--进入登录页面
      2. 是--保存到cookie【注意:密码的保密性】
    2. 再次访问时:
      1. 用户未登录+cookie信息账号密码正确-->>自动登录
      2. 已经登录过,判断账号密码是否正确-->>正确则进行登录
  • 代码示例

    package com.easymall.filter;import java.io.IOException;import java.net.URLDecoder;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import com.easymall.domain.User;import com.easymall.factory.BasicFactory;import com.easymall.service.UserService;public class AautologinFilter implements Filter {    public void destroy() {    }    public void doFilter(ServletRequest arg0, ServletResponse arg1,            FilterChain arg2) throws IOException, ServletException {        HttpServletRequest request = (HttpServletRequest) arg0;        HttpServletResponse response = (HttpServletResponse) arg1;        // 只有未登录的用户        if (request.getSession(false) == null                || request.getSession().getAttribute("user") == null) {            // 只有携带Cookie才自动登录            Cookie[] cookies = request.getCookies();            Cookie autoCookie = null;            for (Cookie cookie : cookies) {                if ("autologin".equals(cookie.getName())) {                    autoCookie = cookie;                }            }            if (autoCookie != null) {                // 只有自动登录cookie保存的用户名正确才能自动登录                String username = URLDecoder.decode(autoCookie.getValue()                        .split("#")[0], "utf-8");                String password = autoCookie.getValue().split("#")[1];                UserService userService = BasicFactory.getFactory().getObj(                        UserService.class);                if (userService.checkUsernameAndPassord(username, password)) {                    // 获取session                    HttpSession session = request.getSession();                    // 在session中加入相应的标记                    session.setAttribute("user", new User(-1, username, null,                            null, null));                    // 回到主页                    response.getWriter().write("登录成功!正在跳转。。。");                    response.setHeader("refresh",                            "2;url=" + request.getContextPath() + "/index.jsp");                }            }        } else {// 已经登录过            // 跳转页面的话,会一直进过滤器哦。。。。        }        // 放行资源        arg2.doFilter(arg0, arg1);    }    public void init(FilterConfig arg0) throws ServletException {    }}

加密

  • MD5加密算法
    • 特点
      1. 任意大小的二进制经过MD5计算得到一个独一无二的128位二进制
      2. 相同的数据得到的MD5得到的结果相同
      3. 不相同的数据得到的MD5得到的结果不同
      4. 通常转化为16进制的32位数据
    • 数据摘要,数据指纹----之后对比
    • 应用
      1. 加密存储数据
      2. 文件的完整性
      3. 数字签名
      4. 。。。
    • EasyMall中,应该加密的地方
      1. Cookie中自动登录的密码的存储
      2. 数据库中存放密码的记录,不应该铭文记录
  • 代码示例

    package com.easymall.utils;import java.math.BigInteger;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;public class MD5Utils {    /**     * 使用md5的算法进行加密     */    public static String md5(String plainText) {        byte[] secretBytes = null;        try {            secretBytes = MessageDigest.getInstance("md5").digest(                    plainText.getBytes());        } catch (NoSuchAlgorithmException e) {            throw new RuntimeException("没有md5这个算法!");        }        String md5code = new BigInteger(1, secretBytes).toString(16);        // 为了防止不够32位,比如一些短的密码生成的数据可能不够32位,那么为了解决这的问题,在数据的前面进行补0操作        for (int i = 0; i < 32 - md5code.length(); i++) {            md5code = "0" + md5code;        }        return md5code;    }}

补充

原创粉丝点击