新增全局过滤器认证鉴权,增强防渗透扫描处理

This commit is contained in:
shengzhang 2021-04-12 03:22:01 +08:00
parent 8c6cd9a668
commit 15b0da6351
17 changed files with 342 additions and 47 deletions

View File

@ -31,7 +31,7 @@
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- sa-token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>

View File

@ -13,9 +13,11 @@ import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
*
*/
@Configuration
public class SaTokenConfiguration implements WebMvcConfigurer {
public class SaTokenConfigure implements WebMvcConfigurer {
// 注册sa-token的拦截器打开注解式鉴权功能
/**
* 注册sa-token的拦截器打开注解式鉴权功能
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册注解拦截器

View File

@ -31,7 +31,7 @@
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- sa-token 权限认证Reactor响应式集成, 在线文档http://sa-token.dev33.cn/ -->
<!-- Sa-Token 权限认证Reactor响应式集成, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>

View File

@ -7,7 +7,7 @@ import com.pj.util.AjaxJson;
import cn.dev33.satoken.filter.SaFilterErrorStrategy;
import cn.dev33.satoken.filter.SaFilterStrategy;
import cn.dev33.satoken.reactor.context.SaReactorFilter;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouterUtil;
import cn.dev33.satoken.stp.StpUtil;
@ -17,7 +17,7 @@ import cn.dev33.satoken.stp.StpUtil;
*
*/
@Configuration
public class SaTokenConfiguration {
public class SaTokenConfigure {
/**
* 注册 [sa-token全局过滤器]
@ -34,7 +34,7 @@ public class SaTokenConfiguration {
public SaFilterStrategy getSaFilterStrategy() {
return r -> {
System.out.println("---------- 进入sa-token全局过滤器 -----------");
SaRouterUtil.match("/test/test", () -> StpUtil.checkLogin());
SaRouterUtil.match("/test/test333", () -> StpUtil.checkLogin());
// SaRouterUtil.match("/user/**", () -> StpUtil.checkPermission("user"));
// SaRouterUtil.match("/admin/**", () -> StpUtil.checkPermission("admin"));
// SaRouterUtil.match("/goods/**", () -> StpUtil.checkPermission("goods"));

View File

@ -1,9 +1,10 @@
<!-- 这是目录树文件 -->
- **开始**
- [介绍](/README)
- [框架](/README)
- [集成](/start/download)
- [示例](/start/example)
- [在SpringBoot环境集成](/start/example)
- [在WebFlux环境集成](/start/webflux-example)
- **使用**
- [登录验证](/use/login-auth)
@ -16,6 +17,7 @@
- [同端互斥登录](/use/mutex-login)
- [注解式鉴权](/use/at-check)
- [路由拦截式鉴权](/use/route-check)
- [全局过滤器](/use/global-filter)
- [花式token](/use/token-style)
- [Token前缀](/use/token-prefix)
- [框架配置](/use/config)

View File

@ -31,6 +31,9 @@ body{font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu
/* .gzh-table td img{width: 100%;} */
/* .gzh-table tr, .gzh-table td{ border: 0px !important;} */
/* tab选项卡优化 */
.docsify-tabs__tab{outline: 0; cursor: pointer;}
.docsify-tabs--classic .docsify-tabs__tab--active{box-shadow: 0 0 0;}
/* ============== 代码样式优化 ================ */

View File

@ -6,11 +6,37 @@
<table class="gzh-table" style="text-align: center;">
<tr>
<td>
<img src="https://mp.weixin.qq.com/mp/qrcode?scene=10000005&size=102&__biz=MjM5NzA1MTcyMA==&mid=2651175957&idx=3&sn=93343b003a8a3c2c600b909499cb554a&send_time="/>
<b>程序猿</b>
<span>传播编程经验,挖掘程序员优秀的学习资源。</span>
</td>
<td>
<img src="https://mp.weixin.qq.com/mp/qrcode?scene=10000005&size=102&__biz=MzI3MDE0NzYwNA==&mid=2651443022&idx=2&sn=65db50021c95493d2df03dc58f6dae49&send_time="/>
<b>架构师必备</b>
<span>分享干货文章,做一个有逼格的架构师社区!</span>
</td>
<td>
<img src="https://mp.weixin.qq.com/mp/qrcode?scene=10000005&size=102&__biz=MzI4MjI1MTI0Mw==&mid=2247493681&idx=1&sn=4257550a48bf3dfc5c312b0750171c61&send_time="/>
<b>GitHuboy</b>
<span>专注于分享 Python、Java、Web、AI、数据分析等多个领域的优质学习资源</span>
</td>
<td>
<img src="https://mp.weixin.qq.com/mp/qrcode?scene=10000005&size=102&__biz=MzA3NzA2MDMyNA==&mid=2650359032&idx=1&sn=79eea2f0cb16d5054bbb731885c310e5&send_time="/>
<b>开源最前线</b>
<span>推荐热门开源软件,介绍新开源项目,报导开源资讯!</span>
</td>
<td></td>
</tr>
<tr>
<td>
<img src="https://mp.weixin.qq.com/mp/qrcode?scene=10000004&size=102&__biz=MzUzNTY2NjAzMg==&mid=2247484321&idx=1&sn=52e7e5e0dc03437e94908b6a67985500&send_time="/>
<b>dromara开源组织</b>
<span>dromara开源组织官方公众号 [https://github.com/dromara][https://gitee.com/dromara]</span>
<b>Dromara开源组织</b>
<span>Dromara开源组织官方公众号</span><br>
<a href="https://gitee.com/dromara" target="_blank">Gitee</a>
<a href="https://github.com/dromara" target="_blank">GitHub</a>
<a href="https://dromara.org/zh/projects/" target="_blank">官网</a>
</td>
<td>
<img src="https://mp.weixin.qq.com/mp/qrcode?scene=10000004&size=102&__biz=MzAxNjk4ODE4OQ==&mid=2247503088&idx=3&sn=f7e82b05d8f155b1fa79601393c437dc&send_time="/>

View File

@ -1,12 +1,11 @@
# 集群、分布式
Sa-token 在集群、分布式下的解决方案
Sa-Token 在集群、分布式下的解决方案
---
### 分布式下的数据同步问题
单机版的`Session`在分布式环境下一般不能正常工作,为此我们需要对框架做一些特定的处理。
### 分布式会话
分布式架构下的第一个难题便是数据同步,单机版的`Session`在分布式环境下一般不能正常工作,为此我们需要对框架做一些特定的处理。
首先我们要明白,分布式环境下为什么`Session`会失效?因为用户在一个节点对会话做出的更改无法实时同步到其它的节点,
这就导致一个很严重的问题:如果用户在节点一上已经登录成功,那么当下一次的请求落在节点二上时,对节点二来讲,此用户仍然是未登录状态。
@ -26,6 +25,12 @@ Sa-token 在集群、分布式下的解决方案
由于`jwt`模式不在服务端存储数据,对于比较复杂的业务可能会功能受限,因此更加推荐使用方案三
### 微服务网关鉴权
由于大多数常见网关组件基于`webflux`编写,从底层上脱离了"ServletAPI"模型(如`Gateway`、`Soul`等这就导致很多底层依赖ServletAPI的权限认证框架无法在网关处使用。
为此`Sa-Token`自`v1.16.0`版本开始提供了`Reactor响应式模型`web框架的starter依赖包你可以据此轻松完成网关鉴权需求
详细请参考:[全局过滤器](/use/global-filter)

View File

@ -3,7 +3,10 @@
------
## Maven依赖
在项目中直接通过 `pom.xml` 导入 `sa-token` 的依赖即可
在项目中直接通过 `pom.xml` 导入 `sa-token` 的依赖即可:
<!-- tabs:start -->
<!-- tab:SpringMVC环境 ServletAPI -->
``` xml
<!-- sa-token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
@ -13,27 +16,46 @@
</dependency>
```
## Gradle依赖
Gradle用户引入依赖
<!-- tab:WebFlux环境 Reactor -->
注:此依赖适合在 Reactor模式 的web框架中导入例如`Netty`、`WebFlux`等),如果您的项目基于 ServletAPI (`SpringMVC`、`SpringBoot`等),请以前者为准
``` xml
<!-- sa-token 权限认证Reactor响应式集成, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>
<version>1.15.2</version>
</dependency>
```
<!-- tabs:end -->
## Gradle依赖
<!-- tabs:start -->
<!-- tab:SpringMVC环境 ServletAPI -->
``` xml
implementation 'cn.dev33:sa-token-spring-boot-starter:1.15.2'
```
<!-- tab:WebFlux环境 Reactor -->
``` xml
implementation 'cn.dev33:sa-token-reactor-spring-boot-starter:1.15.2'
```
<!-- tabs:end -->
## 获取源码
如果你想深入了解`sa-token`,你可以通过`github`或者`gitee`来获取源码
如果你想深入了解`sa-token`,你可以通过`github`或者`gitee`来获取源码 **学习测试请拉取master分支**dev为正在开发的分支有很多特性并不稳定
- github地址[https://github.com/dromara/sa-token](https://github.com/dromara/sa-token)
- gitee地址[https://gitee.com/dromara/sa-token](https://gitee.com/dromara/sa-token)
- 开源不易,求鼓励,给个`star`吧
- 源码目录介绍:
```
``` js
── sa-token
├── sa-token-core // sa-token 核心模块
├── sa-token-servlet // sa-token 整合 Servlet容器实现类包
├── sa-token-spring-boot-starter // sa-token 整合 SpringBoot 快速集成
├── sa-token-webflux-spring-boot-starter // sa-token 整合 WebFlux 快速集成
├── sa-token-reactor-spring-boot-starter // sa-token 整合 Reactor响应式编程 快速集成
├── sa-token-dao-redis // sa-token 整合 Redis (使用jdk默认序列化方式)
├── sa-token-dao-redis-jackson // sa-token 整合 Redis (使用jackson序列化方式)
├── sa-token-spring-aop // sa-token 整合 SpringAOP 注解鉴权

View File

@ -1,21 +1,19 @@
# 示例
# SpringBoot 集成 Sa-Token 示例
本篇将带你从零开始集成sa-token从而让你快速熟悉sa-token的使用姿势 <br>
以Maven + SpringBoot为例
整合示例在官方仓库的`/sa-token-demo-springboot`文件夹下,如遇到难点可结合源码进行测试学习
---
### 1、创建项目
在IDE中新建一个SpringBoot项目例如`sa-token-demo-springboot`不会的同学请自行百度或者参考github示例
## SpringBoot环境
#### 1、创建项目
在IDE中新建一个Springboot项目例如`sa-token-demo-springboot`不会的同学请自行百度或者参考github示例
#### 2、设置jar包依赖
### 2、设置pom包依赖
`pom.xml` 中添加依赖:
``` xml
<!-- sa-token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
@ -23,9 +21,9 @@
</dependency>
```
#### 3、配置文件
你可以**零配置启动项目** <br>
但同时你也可以在`application.yml`中增加如下配置,定制性使用框架:
### 3、设置配置文件
你可以**零配置启动项目** 但同时你也可以在`application.yml`中增加如下配置,定制性使用框架:
``` java
spring:
@ -49,7 +47,7 @@ spring:
百度: [springboot properties与yml 配置文件的区别](https://www.baidu.com/s?ie=UTF-8&wd=springboot%20properties%E4%B8%8Eyml%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%8C%BA%E5%88%AB)
#### 4、创建启动类
### 4、创建启动类
在项目中新建包 `com.pj` ,在此包内新建主类 `SaTokenDemoApplication.java`,输入以下代码:
``` java
@ -62,18 +60,18 @@ public class SaTokenDemoApplication {
}
```
#### 5、运行
### 5、运行
运行代码,当你从控制台看到类似下面的内容时,就代表框架已经成功集成了
![运行结果](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/app-run.jpg)
## 普通Spring环境
### 普通Spring环境
普通spring环境与springboot环境大体无异只不过需要在项目根目录手动创建配置文件`sa-token.properties`来完成配置
## 详细了解
通过这个示例你已经对sa-token有了初步的了解那么现在开始详细了解一下它都有哪些[能力](/use/login-auth)吧
### 详细了解
通过这个示例你已经对sa-token有了初步的了解那么现在开始详细了解一下它都有哪些 [能力](/use/login-auth)

View File

@ -0,0 +1,76 @@
# Spring WebFlux 集成 Sa-Token 示例
WebFlux基于Reactor响应式模型开发有着与标准ServletAPI完全不同的底层架构因此要适配WebFlux, 必须提供与Reactor相关的整合实现
本篇将以WebFlux为例展示sa-token与Reactor响应式模型web框架相整合的示例, **你可以用同样方式去对接其它Reactor模型Web框架**
整合示例在官方仓库的`/sa-token-demo-webflux`文件夹下,如遇到难点可结合源码进行测试学习
---
### 1、创建项目
在IDE中新建一个SpringBoot项目例如`sa-token-demo-webflux`不会的同学请自行百度或者参考github示例
### 2、设置pom包依赖
`pom.xml` 中添加依赖:
``` xml
<!-- Sa-Token 权限认证Reactor响应式集成, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>
<version>1.15.2</version>
</dependency>
```
### 3、设置配置文件
你可以**零配置启动项目** ,但同时你也可以在`application.yml`中增加如下配置,定制性使用框架:
``` java
spring:
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
allow-concurrent-login: false
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
token-style: uuid
```
如果你习惯于 `application.properties` 类型的配置文件,那也很好办: <br>
百度: [springboot properties与yml 配置文件的区别](https://www.baidu.com/s?ie=UTF-8&wd=springboot%20properties%E4%B8%8Eyml%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%8C%BA%E5%88%AB)
### 4、创建启动类
在项目中新建包 `com.pj` ,在此包内新建主类 `SaTokenDemoApplication.java`,输入以下代码:
``` java
@SpringBootApplication
public class SaTokenDemoApplication {
public static void main(String[] args) throws JsonProcessingException {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("启动成功sa-token配置如下" + SaTokenManager.getConfig());
}
}
```
### 5、运行
运行代码,当你从控制台看到类似下面的内容时,就代表框架已经成功集成了
![运行结果](https://color-test.oss-cn-qingdao.aliyuncs.com/sa-token/app-run.jpg)

View File

@ -84,11 +84,11 @@ mode有两种取值
## 2、使用拦截器模式
使用AOP方式需要引入新的pom依赖与此相比拦截器模式显的更加轻量级 <br>
你只需要将sa-token的注解校验拦截器注册到你的项目中即可打开注解鉴权功能 <br>
以`SpringBoot2.0`为例, 新建配置类`MySaTokenConfig.java`
以`SpringBoot2.0`为例, 新建配置类`SaTokenConfigure.java`
``` java
@Configuration
public class MySaTokenConfig implements WebMvcConfigurer {
public class SaTokenConfigure implements WebMvcConfigurer {
// 注册sa-token的注解拦截器打开注解式鉴权功能
@Override
public void addInterceptors(InterceptorRegistry registry) {

View File

@ -35,11 +35,11 @@ spring:
* sa-token代码方式进行配置
*/
@Configuration
public class MySaTokenConfig {
public class SaTokenConfigure {
// 获取配置Bean (以代码的方式配置sa-token, 此配置会覆盖yml中的配置)
@Primary
@Bean(name="MySaTokenConfig")
@Bean(name="SaTokenConfigure")
public SaTokenConfig getSaTokenConfig() {
SaTokenConfig config = new SaTokenConfig();
config.setTokenName("satoken"); // token名称 (同时也是cookie名称)

View File

@ -0,0 +1,103 @@
# 全局过滤器
---
### 组件简述
上一节我们学习了“根据拦截器实现路由拦截鉴权”其实在大多数web框架中使用过滤器可以实现同样的功能本章我们就利用sa-token全局过滤器来实现路由拦截器鉴权。
首先我们先梳理清楚一个问题,既然拦截器已经可以实现路由鉴权,为什么还要用过滤器再实现一遍呢?简而言之:
1. 相比于拦截器,过滤器更加底层,执行时机更靠前,有利于防渗透扫描
2. 过滤器可以拦截静态资源,方便我们做一些权限控制
3. 部分Web框架根本就没有提供拦截器功能但几乎所有的Web框架都会提供过滤器机制
但是过滤器也有一些缺点,比如:
1. 由于太过底层,导致无法率先拿到`HandlerMethod`对象,无法据此添加一些额外功能
2. 由于拦截的太全面了,导致我们需要对很多特殊路由(如`/favicon.ico`)做一些额外处理
3. 在Spring中过滤器中抛出的异常无法进入全局`@ExceptionHandler`,我们必须额外编写代码进行异常处理
Sa-Token同时提供过滤器和拦截器机制不是为了让谁替代谁而是为了让大家根据自己的实际业务合理选择拥有更多的发挥空间。
### 注册过滤器
同拦截器一样为了避免不必要的性能浪费sa-token全局过滤器默认处于关闭状态若要使用过滤器组件首先你需要注册它到项目中
``` java
/**
* [Sa-Token 权限认证] 配置类
* @author kong
*/
@Configuration
public class SaTokenConfigure {
/**
* 注册 [sa-token全局过滤器]
*/
@Bean
public SaServletFilter getSaReactorFilter() {
return new SaServletFilter();
}
/**
* 注册 [sa-token全局过滤器-认证策略]
*/
@Bean
public SaFilterStrategy getSaFilterStrategy() {
return r -> {
System.out.println("---------- 进入sa-token全局过滤器 -----------");
// 登录验证 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
SaRouterUtil.match("/**", "/user/doLogin", () -> StpUtil.checkLogin());
// 权限认证 -- 不同模块, 校验不同权限
SaRouterUtil.match("/user/**", () -> StpUtil.checkPermission("user"));
SaRouterUtil.match("/admin/**", () -> StpUtil.checkPermission("admin"));
SaRouterUtil.match("/goods/**", () -> StpUtil.checkPermission("goods"));
SaRouterUtil.match("/orders/**", () -> StpUtil.checkPermission("orders"));
SaRouterUtil.match("/notice/**", () -> StpUtil.checkPermission("notice"));
SaRouterUtil.match("/comment/**", () -> StpUtil.checkPermission("comment"));
// 匹配 restful 风格路由
SaRouterUtil.match("/article/get/{id}", () -> StpUtil.checkPermission("article"));
};
}
/**
* 注册 [sa-token全局过滤器-异常处理策略]
*/
@Bean
public SaFilterErrorStrategy getSaFilterErrorStrategy() {
return e -> AjaxJson.getError(e.getMessage());
}
}
```
### 注意事项
- 在`[认证策略]`里,你可以和拦截器里一致的代码,进行路由匹配鉴权
- 由于过滤器中抛出的异常不进入全局异常处理,所以你必须提供`[异常处理策略]`来处理`[认证策略]`里抛出的异常
- 在`[异常处理策略]`里的返回值,将作为字符串输出到前端,如果需要定制化返回数据,请注意其中的格式转换
### 在WebFlux中使用过滤器
`Spring WebFlux`中不提供拦截器机制,因此若你的项目需要路由鉴权功能,过滤器是你唯一的选择,在`Spring WebFlux`注册过滤器的流程与上述流程几乎完全一致,
除了您需要将过滤器名称由`SaServletFilter`更换为`SaReactorFilter`以外,其它所有步骤均可参考以上示例
``` java
/**
* [Sa-Token 权限认证] 配置类
* @author kong
*/
@Configuration
public class SaTokenConfigure {
/**
* 注册 [sa-token全局过滤器]
*/
@Bean
public SaReactorFilter getSaReactorFilter() {
return new SaReactorFilter();
}
// 其它代码 ...
}
```

View File

@ -10,10 +10,10 @@
## 1、注册路由拦截器
以`SpringBoot2.0`为例, 新建配置类`MySaTokenConfig.java`
以`SpringBoot2.0`为例, 新建配置类`SaTokenConfigure.java`
``` java
@Configuration
public class MySaTokenConfig implements WebMvcConfigurer {
public class SaTokenConfigure implements WebMvcConfigurer {
// 注册sa-token的登录拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
@ -31,7 +31,7 @@ public class MySaTokenConfig implements WebMvcConfigurer {
``` java
@Configuration
public class MySaTokenConfig implements WebMvcConfigurer {
public class SaTokenConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册路由拦截器,自定义验证规则
@ -53,7 +53,7 @@ public class MySaTokenConfig implements WebMvcConfigurer {
``` java
@Configuration
public class MySaTokenConfig implements WebMvcConfigurer {
public class SaTokenConfigure implements WebMvcConfigurer {
// 注册sa-token的拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {

View File

@ -1,4 +1,4 @@
package cn.dev33.satoken.reactor.context;
package cn.dev33.satoken.reactor.filter;
import org.springframework.core.annotation.Order;
import org.springframework.web.server.ServerWebExchange;
@ -6,6 +6,8 @@ import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.reactor.context.SaReactorHolder;
import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
import cn.dev33.satoken.util.SaTokenConsts;
import reactor.core.publisher.Mono;

View File

@ -0,0 +1,56 @@
package cn.dev33.satoken.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;
import org.springframework.core.annotation.Order;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.util.SaTokenConsts;
/**
* Servlet全局过滤器
* @author kong
*
*/
@Order(SaTokenConsts.ASSEMBLY_ORDER)
public class SaServletFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
// 执行全局过滤器
SaTokenManager.getSaFilterStrategy().run(null);
} catch (Throwable e) {
// 1. 获取异常处理策略结果
Object result = SaTokenManager.getSaFilterErrorStrategy().run(e);
String resultString = String.valueOf(result);
// 2. 写入输出流
response.setContentType("text/plain; charset=utf-8");
response.getWriter().print(resultString);
return;
}
// 执行
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}