애플리케이션 권한 관리 필터링 및 민감한 단어 필터링

방금 Filter에 대한 응용 프로그램을 만들었고 머리가 뜨거울 때 빠르게 기록했습니다.이 기사에는 두 가지 작은 응용 프로그램이 있습니다. 하나는 권한 관리 에 관한 것 입니다. * 권한 관리 란 무엇입니까? * 로그인하지 않은 상태에서는 아무것도 할 수 없다는 뜻입니다.이 조작은 매우 익숙합니다. 예를 들어, Tmall의 주문 시스템은 로그인하지 않은 경우에만 열람 할 수 있으며 주문 및 결제를 제출할 수 없습니다. 먼저 로그인하라는 메시지가 표시됩니다. 또 다른 일반적인 예는 일부 웹 사이트의 로그인 쿼리 시스템입니다. 로그인하지 않으면 정보를 볼 수 없습니다. 이것은 권한 관리입니다. 이것의 장점은 매우 안전하다는 것입니다. 일부 안전하지 않은 요소를 필터링합니다. 일반적으로 현재 로그인을 포함하는 한 웹 사이트는 기본적으로 필터를 사용하여 권한 관리 작업을 수행합니다. 또 다른 작은 응용 프로그램은 민감한 단어필터링하는 것 입니다.이 응용 프로그램은 더 일반적입니다.이 예제는 모든 곳에서 볼 수 있습니다. 예를 들어 Canyon of Kings에서 당신은 Zuan 출신이고 그 반대는 매우 훌륭하거나 당신도 매우 훌륭합니다. 그리고 그 반대가 당신을 뿌립니다. 그러면 당신은 Zuan 사람들의 좋은 피를 이용하여 스프레이를 시작합니다. 이때 당신은 대화 상자 에서 "I ** You * **"를 찾을 있습니다 . 많은 저, 당신과 별표 어휘 필터링 작업, 다음으로 우리는 다음과 같은 민감한 단어 필터링을 구현하는 데 중점을 둡니다.
권한 관리에 관해서는 실제로 구현이 매우 간단합니다. 일반적인 아이디어는 먼저 액세스하려는 리소스가 로그인과 관련이 있는지 확인하는 것입니다. 예를 들어 login.jsp는 필터링되지 않고 다음과 같은지 여부를 판단 할 수 있습니다. 로그인 여부는 세션에 의해 판단됩니다. 성공적으로 로그인하면 세션에 매개 변수를 저장하고 매개 변수가 필터에 있는지 확인합니다. 브라우저를 열고 로그인하지 않은 경우 매개 변수가 비어 있어야합니다. 이때 다른 리소스에 액세스하려는 경우 차단됩니다. 필터 코드는 다음과 같습니다.

 @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //强制转换
        HttpServletRequest request = (HttpServletRequest) req;

        //获取请求的资源路径 看是否是登录相关的资源
        String uri = request.getRequestURI();

        //判断
        if (uri.contains("/index.jsp") || uri.contains("/UserLoginServlet") ||uri.contains("/JSP/css/") || uri.contains("/JSP/js/")){
            //包含 证明用户就是想登陆 放行
            chain.doFilter(req, resp);
        }else{
            //不包含 验证用户是否已经登录
            if (request.getSession().getAttribute("user") != null){
                //已经登陆 放行
                chain.doFilter(req, resp);
            }else {
                System.out.println("您被拦截了,您需要先登录" );
                request.setAttribute("longinmessage","您尚未登录,请先登录!");
                request.getRequestDispatcher("/index.jsp").forward(request, resp);
            }
        }
    }

그런 다음 민감한 단어의 차폐를 실현하는 작업에 집중 해 보겠습니다.이 작업의 아이디어는 매우 간단합니다. 즉, 여러 가지 민감한 단어를 한 줄에 하나씩 포함하는 txt 파일이 있습니다. 민감한 단어로 문장을 입력하는 메소드를 호출하면 민감한 단어가 별표로 대체됩니다.이 대체 작업은 요청 메소드에서 구현할 수 없으므로 프록시 모드를 사용해야합니다. 이것이 문제입니다. * 프록시 모드를 사용하는 이유는 무엇입니까? * 예를 request.getParameter("name");들어이 문 을 호출 할 때 이름에할당하지만이 메소드 자체는 민감한 문자의 대체를 지원하지 않습니다. 민감한 단어가있는 경우 대체 할 수 있도록이 메소드의 기능을 강화해야합니다. 전화.
그럼 먼저 에이전시 모델이 무엇인지 얘기해 봅시다.
프록시 모드는 위에서 언급 한 방법의 강화 필터링 기능과 같이 일부 방법의 기능을 강화할 수 있습니다.이 방법을 향후 호출 할 때 일부 민감한 단어를 걸러 낼 것입니다. 기능을 강화하기위한 디자인 패턴도 있습니다. 데코레이터 모드 라고 부르는이 두 가지 모두 향상된 메서드의 기능을 수행 할 수 있습니다. 에이전시 모델은 이름에서 알 수 있듯이 에이전트 모델을 가지고 있습니다. 에이전트가 있으면 진짜 빅 보스가 있어야합니다. 에이전트는 일상 생활의 예처럼 빅 보스로부터 상품을받습니다. 많은 신발이 판매됩니다. Putian에는 큰 소가 많고 그 아래에 에이전트가 많이 있습니다. 우리는 직접 큰 보스를 찾는 대신 에이전트를 통해 신발을 구매합니다. 예를 들어, 빅 보스가이 신발 한 켤레를 800에 팔았고 에이전트가 900에 성공적으로 샀습니다. 에이전트는 가격을 올렸고 저에게 눈물을 흘리며 100 달러를 벌었습니다. 그럼 직접 대장에게 가보는 건 어떨까요? 가격이 너무 높거나 보스를 찾을 수 없기 때문에 에이전트를 통해서만 상품을 얻을 수 있습니다. 이런 식으로 에이전시 모델은 많은 것을 이해하게 될 것입니다. 에이전트는 빅 보스를 위해 행동합니다. 우리는 에이전트로부터 물품을 얻고 빅 보스로부터 물품을 얻는 목적을 달성합니다 .
간단한 예를 사용하여 설명해 보겠습니다. 먼저 인터페이스를 생성 해 보겠습니다. 에이전트이든 큰 보스가 신발을 판매하든 관련 방법을 설명하기위한 인터페이스가 필요합니다.

package proxy;

/**
 * @author Shi Jun Yi
 * @version 1.0
 * @date 2021/1/25 12:32
 */
public interface SaleComputer {

    public String sale(double money);

    public void show();
}

이 인터페이스를 사용하면 실제 빅 보스 오브젝트가 있어야합니다.

package proxy;

/**
 * @author Shi Jun Yi
 * @version 1.0
 * @date 2021/1/25 12:34
 */
public class Lenovo implements SaleComputer {
    @Override
    public String sale(double money) {
        System.out.println("花了"+money+"元买了一双回到未来....");
        return "耐克鞋子";
    }

    @Override
    public void show() {
        System.out.println("展示鞋子.....");
    }
}

다음으로 테스트 클래스를 작성합니다.

package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author Shi Jun Yi
 * @version 1.0
 * @date 2021/1/25 12:35
 */
public class ProxyTest {

    public static void main(String[] args ){
        //创建真实对象
        Lenovo lenovo = new Lenovo();

        //动态代理 增强lenovo对象
        /*
            三个参数
                类加载器 真实对象
                接口数组 真实对象
                处理器 很重要 核心业务逻辑
         */
        SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
            /*
                代理逻辑 代理对象调用的所有的方法都会触发该方法
                    参数
                        1 代理对象
                        2 代理对象调用的方法
                        3 调用对象的时候传递的参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               /* System.out.println("该方法被执行了......");
                System.out.println(method.getName());
                System.out.println(args[0]);*/

               //使用真实对象的方法调用该方法

                if(method.getName().equals("sale")){
                    //增强参数
                    double money = (double)args[0];
                    money = money*0.85;
                    System.out.println("专车接....");
                    String obj = (String) method.invoke(lenovo, money);
                    System.out.println("专车送....");
                    //增强返回值
                    return obj+"_鞋垫";
                }else{
                    Object obj = method.invoke(lenovo,args);
                    return obj;
                }
            }
        });

        //调用方法
        String computer = proxy_lenovo.sale(80000);

        System.out.println(computer);
    }
}

여기에 사진 설명 삽입
그런 다음 일반적인 구현 단계에 대해 이야기 해 보겠습니다.

  1. 프록시 모드이므로 실제 객체를 프록시해야하므로 새 실제 객체를 만듭니다.
  2. 고정 된 형식 Proxy.newProxyInstance(....)형식을 통해 실제 객체의 프록시를 실현합니다.이 메서드에는 핵심 향상된 논리를 포함하는 재정의 된 invoke 메서드가 있습니다. 프록시 논리 프록시 객체에서 호출하는 모든 메서드가 메서드를 트리거합니다.
  3. invoke 메소드에는 3 개의 매개 변수가 있는데 첫 번째 매개 변수는 프록시 객체이고 두 번째 매개 변수는 프록시 객체가 호출하는 메소드이며 프록시 객체가 메소드를 호출 할 때 전달되는 매개 변수입니다.
  4. String computer = proxy_lenovo.sale(80000);sale 메서드를 호출하고 있으므로 메서드 이름이 sale인지 아닌지 확인해야합니다. 그렇다면 반환 값이 향상되고 그렇지 않으면 메서드가 기본적으로 실행됩니다. 이 향상 메서드의 구현은 실제로 이전에 향상되지 않은 메서드를 먼저 실행 한 다음 향상되지 않은 반환 값에 일부 콘텐츠를 추가하고 향상된 메서드의 효과를 얻기 위해 새 반환 값을 반환하는 것입니다.
  5. 우리 프록시 객체가 호출 한 메소드가 sale 일 때 매개 변수를 먼저 전달한 다음이 매개 변수에 0.85를 곱하고 실제 객체의 메소드가 실행되고 값이 반환됩니다. String obj = (String) method.invoke(lenovo, money);이 문장이 문장입니다. 실제 개체의 메서드를 호출합니다. 반환 값을 얻은 후 반환 값에 내용을 추가하고 출력을 반환합니다.
    이것은 간단한 구현입니다. 다음으로 민감한 단어 문제로 돌아갑니다.
    먼저 "sensitive words.txt"라는 파일을 생성합니다. 내용은 다음과 같습니다.
    여기에 사진 설명 삽입
    매우 Zuan 단어를 말하지 않고 너무 민감
    합니다. 직접 추가 합니다 ~ 먼저 sesitivewordsfilter 라는 새 필터를 생성합니다 . 당연히 doFlter 메소드 에서 문자 필터링 작업 수행 해야합니다 . 처음에는 프록시 객체를 생성합니다. 모드는 위와 동일합니다. 향상 메소드를 수행하기 전에 먼저 민감한 어휘 .txt 파일을로드해야합니다. 초기화 레코드 파일은 init에 위치해야합니다. 메소드에서는 먼저 민감한 단어 모음이 있어야합니다. private List<String> list = new ArrayList<>();inti 메소드에는 config라는 매개 변수가 있습니다. config config.getServletContext().getRealPath("敏感词汇.txt");메소드를 사용하여 파일을로드하고 읽을 수 있습니다. 로드 후. IO 스트림에 대한 지식을 사용합니다. 버퍼가있는 파일을 사용하여 파일을 읽은 다음 파일의 BufferedReader br = new BufferedReader(new FileReader(contextPath));각 줄을 컬렉션에 추가합니다. 파일을 읽을 때 스트림을 닫아서 모든 민감한 정보를 단어는 목록 컬렉션에 저장되며 포함 여부 만 비교하면됩니다. 먼저 요청의 getParameter 메서드를 개선해 보겠습니다. 첫 번째 단계는 기본 제공 매개 변수 목록을 통해 메서드인지 아닌지 확인하는 것입니다.method.getName();메서드 이름을 반환하려면 원래 getPramenter 메서드를 실행하고 해당 값을 반환합니다. 반환 후 반환 값이 비어 있지 않은 경우 목록 조합을 탐색하여 반환 값에 목록 모음에서 민감한 단어가 포함되어 있는지 확인합니다. 포함되어 있으면 별표로 바꿉니다. 호출 된 getParamenter 메소드가 아닌 경우 원래 매개 변수 return method.invoke(req,args);chain.doFilter(proxy_req, resp);반환 하고 마지막으로 향상된 요청을 반환합니다.
    필터 코드 :
package filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Shi Jun Yi
 * @version 1.0
 * @date 2021/1/25 15:03
 * 敏感词汇过滤器
 */
@WebFilter(filterName = "SensitiveWordsFilter", value = "/TestServlet")
public class SensitiveWordsFilter implements Filter {
    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //创建代理对象 增强getParameter方法
        ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //增强方法 先判断是否是该方法
                if (method.getName().equals("getParameter")){
                    //增强返回值
                    String value = (String)method.invoke(req, args);
                    if (value != null){
                        for (String str:list) {
                            if (value.contains(str)){
                                value = value.replaceAll(str,"***");
                            }
                        }
                    }
                    return value;
                }

                //增强getAttribute方法
                if (method.getName().equals("getAttribute")){
                    //增强返回值
                    String value = (String) method.invoke(req, args);
                    if (value != null){
                        for (String str:list) {
                            if (value.contains(str)){
                                value = value.replaceAll(str,"**");
                            }
                        }
                    }
                    return value;
                }

                return method.invoke(req,args);
            }
        });

        //放行增强后的request方法
        chain.doFilter(proxy_req, resp);
    }

    //放敏感词汇集合
    private List<String> list = new ArrayList<>();

    @Override
    public void init(FilterConfig config) throws ServletException {

        try{
        //加载文件
            String contextPath = config.getServletContext().getRealPath("敏感词汇.txt");

            //读取文件
            BufferedReader br = new BufferedReader(new FileReader(contextPath));

            //将文件的每一行添加到list当中
            String line = null;
            while ((line = br.readLine()) != null){
                list.add(line);
             }
             br.close();
            System.out.println(list);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

향상된 메소드를 호출하기 위해 새로운 서블릿을 생성합니다.

package control;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Shi Jun Yi
 * @version 1.0
 * @date 2021/1/25 15:33
 */
@WebServlet(name = "TestServlet", value = "/TestServlet")
public class TestServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");
        String msg = request.getParameter("msg");

        request.setAttribute("name2", "我diu,你这个大笨蛋,大SB...");
        System.out.println(request.getAttribute("name2"));

        System.out.println(name+":"+msg);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

다음으로 효과를 확인합니다 :
여기에 사진 설명 삽입
여기에 사진 설명 삽입
효과가 나쁘지 않습니다. hhh ~~, 위 내용은이 블로그의 내용입니다. 단점이 있으면 지적 해주세요, 감사합니다.

참조 콘텐츠 : https://www.bilibili.com/video/BV1u7411Z769?p=12

추천

출처blog.csdn.net/weixin_44475741/article/details/113118081