Filterに関するアプリケーションを作成したところ、脳が熱くなっている間にすばやく記録しました。この記事には2つの小さなアプリケーションがあります。1つは権限管理に関するものです。*権限管理とは何ですか。*ログインしていないときは何もできないという意味です。この操作はなじみがあります。たとえば、Tmallの注文システムは、ログインしていないときだけ閲覧でき、注文や支払いを送信することはできません。送信するとき注文最初にログインするように通知されます。もう1つの一般的な例は、一部のWebサイトのログインクエリシステムです。ログインしていないと、情報を表示できません。これは権限管理です。これの利点は、非常に安全であるということです。いくつかの安全でない要素を除外します。ログインを伴う限り、Webサイトは基本的にフィルターを使用してこの権限管理操作を実行します。もう1つの小さなアプリケーションは、機密性の高い単語をフィルタリングすることです。このアプリケーションはより一般的です。この例はどこにでも見られます。たとえば、キャニオンオブキングスでは、あなたはズアン出身で、その反対は非常に優れています。反対にスプレーします。それからズアンの人々の良い血を利用してスプレーを開始します。このとき、チャットボックスに「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);
}
}
}
次に、機密性の高い単語のシールドを実現する操作に焦点を当てましょう。この操作の考え方は非常に単純です。つまり、1行に1つの機密性の高い単語を含むさまざまな機密性の高い単語を含むtxtファイルがあります。メソッドを呼び出してセンシティブワードを含む文を入力すると、センシティブワードがアスタリスクに置き換えられます。この置換操作はリクエストメソッドでは実装できないため、プロキシモードを使用する必要があります。これが問題です。*なぜプロキシモードを使用するのですか?*たとえば、request.getParameter("name");
このステートメントを呼び出すときは、名前に値を割り当てますが、このメソッド自体は機密文字の置換をサポートしていません。このメソッドの機能を拡張して、機密単語が置き換えられるようにする必要があります。と呼ばれる。
それでは、まずエージェンシーモデルとは何かについてお話ししましょう。
プロキシモードは、上記のメソッドの拡張フィルタリング機能と同様に、一部のメソッドの機能を拡張できます。将来このメソッドを呼び出すと、一部の機密性の高い単語が除外されます。の機能を拡張するためのデザインパターンもあります。デコレータモードと呼ばれるこれらの両方は、拡張されたメソッドの機能を実現できます。エージェンシーモデルは、その名のとおり、エージェントのモデルがあります。エージェントがいるとしたら、本当のビッグボスがいるはずです。エージェントは、私たちの日常生活の例のように、ビッグボスから商品を受け取ります。多くの靴が売られています。莆田には大きな牛がたくさんいて、その下にはたくさんのエージェントがいます。私たちはビッグボスを直接探すのではなく、エージェントを通して靴を購入しています。たとえば、大ボスがこの靴を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);
}
}
次に、一般的な実装手順について説明しましょう。
- これはプロキシモードであるため、実オブジェクトをプロキシする必要があるため、新しい実オブジェクトを作成します。
- 固定フォーマット
Proxy.newProxyInstance(....)
形式で実オブジェクトのプロキシを実現します。このメソッドには、コア拡張ロジックを含むオーバーライドされたinvokeメソッドがあります。プロキシロジックプロキシオブジェクトによって呼び出されるすべてのメソッドがメソッドをトリガーします。 - invokeメソッドには3つのパラメーターがあります。最初のパラメーターはプロキシオブジェクト、2番目のパラメーターはプロキシオブジェクトによって呼び出されるメソッド、およびプロキシオブジェクトがメソッドを呼び出すときに渡されるパラメーターです。
String computer = proxy_lenovo.sale(80000);
saleメソッドを呼び出しているので、メソッド名がsaleであるかどうかを判断する必要があります。そうである場合、戻り値は拡張されます。そうでない場合、メソッドはデフォルトで実行されます。この拡張メソッドの実装は、実際には、以前に拡張されていないメソッドを最初に実行し、次に拡張されていない戻り値にコンテンツを追加し、新しい戻り値を返して拡張メソッドの効果を実現することです。- プロキシオブジェクトによって呼び出されたメソッドがsaleの場合、最初にパラメータが渡され、次にこのパラメータに0.85が乗算され、実際のオブジェクトのメソッドが実行されて値が返されます。
String obj = (String) method.invoke(lenovo, money);
この文はステートメントです。これは、実際のオブジェクトのメソッドを呼び出します。戻り値を取得したら、戻り値にコンテンツを追加して出力を返します。
これは単純な実装です。次に、デリケートな言葉の問題に戻ります。
まず、「sensitivewords.txt」という名前のファイルを作成します。内容は次のとおりです。
極端なズアン語は言いません。機密性が高すぎます。自分で追加し
てください〜最初に、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 ~~、上記はこのブログの内容です。何か欠点があれば、指摘してください、ありがとうございます。