Springboot 自定义过滤器(Filter)过滤请求做权限验证

Springboot 自定义过滤器(Filter)过滤请求做权限验证

1.自定义权限验证过滤器

使用 jwt生产令牌(token),鉴权。

/**
 * @Author: lijia
 * @Description: 权限验证过滤器
 * @CreateDate: 2021/5/21 11:56
 */
//标识filter
@WebFilter(filterName = "AuthenticationFilter", urlPatterns = {"/adminService/*", "/otherService/*"})
public class AuthenticationFilter implements Filter {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    //忽略请求地址
    public List<String> ignoreUrl
            = Arrays.asList(
            "/adminService/auth/token",
            "/adminService/auth/refreshToken");

    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("AuthenticationFilter---->init()");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        //获取请求URI
        String requestURI = httpRequest.getRequestURI();
        if (ignoreUrl.contains(requestURI)) {
            //放行
            filterChain.doFilter(httpRequest, httpResponse);
        } else {
            // 从 http 请求头中取出 token
            String token = httpRequest.getHeader("token");
            //没有token
            if (StringUtil.isBlank(token)) {
                BaseResponse baseResponse = new BaseResponse();
                baseResponse.setMessage("token不能为空!")
                    		.setCode(SystemResponseStatusCode.TOKEN_NONE);
                httpServletResponse.setStatus(SystemResponseStatusCode.UNAUTHORIZED);
                httpServletResponse.setContentType("application/json; charset=UTF-8");
                httpServletResponse.getWriter()
                    			   .write(JSONObject.toJSONString(baseResponse));
            } else {
                // 自定义前缀
                String prefix = "WEB";
                // 校验token,解析出userId
                String userId = verifyJWT(token, prefix);
                if (StringUtil.isBlank(userId)) {
                    BaseResponse baseResponse = new BaseResponse();
                    baseResponse.setMessage("token错误!")
                        		.setCode(SystemResponseStatusCode.TOKEN_NONE);
                    httpResponse.setStatus(SystemResponseStatusCode.UNAUTHORIZED);
                    httpResponse.setContentType("application/json; charset=UTF-8");
                    httpResponse.getWriter()
                        .write(JSONObject.toJSONString(baseResponse));
                } else {
                    // 判断token是否过期
                    String key = MD5Helper.md5(userId);
                    Object tokenObject = redisTemplate.opsForHash().get(key, "token");
                    String redisToken=tokenObject==null?"" : String.valueOf(tokenObject);
                    if (!token.equals(redisToken)) {
                        BaseResponse baseResponse = new BaseResponse();
                        baseResponse.setMessage("token失效!")
                            .setCode(SystemResponseStatusCode.TOKEN_NONE);
                        httpResponse.setStatus(SystemResponseStatusCode.UNAUTHORIZED);
                        httpResponse.setContentType("application/json; charset=UTF-8");
                        httpResponse.getWriter()
                            .write(JSONObject.toJSONString(baseResponse));
                    } else {
                        HeaderMapRequestWrapper requestWrapper = new HeaderMapRequestWrapper(httpServletRequest);
                        requestWrapper.addHeader("userId", userId);
                        filterChain.doFilter(requestWrapper, httpServletResponse);
                    }
                }
            }
        }
    }

    @Override
    public void destroy() {
    }
    /**
     * JWT验证
     * @param token prefix
     * @return urserId
     */
    private String verifyJWT(String token, String prefix) {
        String userId;
        try {
            Algorithm algorithm = Algorithm.HMAC256(prefix);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("userId")
                    .build();
            DecodedJWT decodedJWT = verifier.verify(token);
            userId = decodedJWT.getClaim("userId").asString();
        } catch (JWTVerificationException e) {
            e.printStackTrace();
            return "";
        }
        return userId;
    }
}

请求头参数包装类

/**
 * @Author: lijia
 * @Description: 请求头参数包装
 * @CreateDate: 2021/5/19 14:40
 */
public class HeaderMapRequestWrapper extends HttpServletRequestWrapper {
    /**
     * construct a wrapper for this request
     *
     * @param request
     */
    public HeaderMapRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    private Map<String, String> headerMap = new HashMap<>();

    /**
     * add a header with given name and value
     *
     * @param name
     * @param value
     */
    public void addHeader(String name, String value) {
        headerMap.put(name, value);
    }

    @Override
    public String getHeader(String name) {
        String headerValue = super.getHeader(name);
        if (headerMap.containsKey(name)) {
            headerValue = headerMap.get(name);
        }
        return headerValue;
    }

    /**
     * get the Header names
     */
    @Override
    public Enumeration<String> getHeaderNames() {
        List<String> names = Collections.list(super.getHeaderNames());
        for (String name : headerMap.keySet()) {
            names.add(name);
        }
        return Collections.enumeration(names);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {

        List<String> values = Collections.list(super.getHeaders(name));
        if (headerMap.containsKey(name)) {
            values = Arrays.asList(headerMap.get(name));
        }
        return Collections.enumeration(values);
    }
}

2.程序启动类加入扫描

@WebFilter注解是由Servlet提供的,Springboot默认是不会扫描到该注解。

@MapperScan("com.lijia.dao")
@EnableSwagger2
@SpringBootApplication(scanBasePackages = "com.lijia")
//扫描Servlet的注解
@ServletComponentScan(basePackages = "com.lijia.filter")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3.使用FilterRegistrationBean手动注册过滤器

@Bean
public FilterRegistrationBean filterRegistration() {
   FilterRegistrationBean registrationBean = new FilterRegistrationBean();
   registrationBean.setFilter(authenticationFilter());
   registrationBean.addUrlPatterns("/*");
   registrationBean.setName("authenticationFilter");
   //设置优先级,数越小优先级越高
   registrationBean.setOrder(1);
   return registrationBean;
}

@Bean
public Filter authenticationFilter() {
     return new AuthenticationFilter();
}

4.注意事项

  • 当使用springboot提供的注解(@Component 、@Configuration)来标识自定义过滤器时,@WebFilter注解的urlPatterns参数配置会失效,默认变成了 urlPatterns="/*"。

  • 在自定义过滤器使用@Autowired自动装载注入Bean可能为null。解决:使用WebApplicationContextUtils来获取

    ServletContext servletContext = servletRequest.getServletContext();
    WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
    Bean bean=webApplicationContext.getBean(Bean.class);
    
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 在 Spring Boot 中实现过滤器有两种方法: 1. 通过编写过滤器类并使用注解 @WebFilter 将其注册为过滤器。例如: ``` @WebFilter(urlPatterns = "/*") public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 处理过滤逻辑 chain.doFilter(request, response); } } ``` 2. 通过编写过滤器类并通过编写配置类来注册过滤器。例如: ``` @Configuration public class WebConfiguration { @Bean public FilterRegistrationBean<MyFilter> filterRegistrationBean() { FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new MyFilter()); registrationBean.addUrlPatterns("/*"); return registrationBean; } } ``` 注意:在 Spring Boot 2.3 及更高版本中,使用注解 @WebFilter 注册过滤器时,需要添加以下依赖: ``` <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> ``` 在 Spring Boot 2.2 及更低版本中,不需要添加此依赖。 ### 回答2: Spring Boot可以通过使用过滤器Filter)实现对于应用程序的请求进行预处理或后处理的功能。在Spring Boot中,实现过滤器非常简单。 首先,我们需要创建一个实现javax.servlet.Filter接口的过滤器类。我们可以在过滤器类中实现对请求的预处理或后处理逻辑。例如,我们可以在过滤器中对请求进行日志记录、授权验证、防止跨站点请求伪造(CSRF)等操作。 接下来,我们需要在Spring Boot应用程序的配置文件(例如application.properties或application.yml)中配置过滤器。我们可以使用Spring Boot提供的特定属性来配置过滤器的顺序、URL匹配模式和其他属性。例如,我们可以使用以下配置来注册并配置过滤器spring.servlet.filter.order=1 spring.servlet.filter.dispatcher-types=REQUEST spring.servlet.filter.url-pattern=/api/* spring.servlet.filter.init-param.debug=true 最后,我们需要在Spring Boot应用程序的启动类(例如带有@SpringBootApplication注解的主类)中添加一个注解@ServletComponentScan,以扫描并注册我们创建的过滤器类。这将使Spring Boot自动识别并加载该过滤器。 实现过滤器后,当应用程序收到请求时,过滤器将自动拦截请求并执行预处理或后处理逻辑。过滤器的执行顺序可以通过配置文件中的spring.servlet.filter.order属性进行调整。 通过以上步骤,我们就可以在Spring Boot应用程序中实现一个过滤器过滤器可以帮助我们在请求到达控制器之前或返回给客户端之前对请求进行额外处理,从而实现对请求自定义处理逻辑。 ### 回答3: Spring Boot提供了一种简单且易于实现的方式来实现过滤器。在Spring Boot中,我们可以通过创建一个实现了javax.servlet.Filter接口的类来实现过滤器。 首先,我们需要在Spring Boot应用程序的代码中创建一个新的类并实现Filter接口。该类需要实现doFilter方法,该方法的目的是在请求进入Web应用程序之前或之后执行一些操作。该方法接受三个参数,分别是ServletRequest、ServletResponse和FilterChain。 在doFilter方法中,我们可以编写我们的逻辑代码来进行过滤操作。例如,我们可以检查请求的URL,如果满足我们的条件,则可以进行一些特定的处理,比如记录日志、验证权限等。然后,我们需要调用FilterChain对象的doFilter方法,以便将请求传递给下一个过滤器或Web应用程序。 接下来,我们还需要在Spring Boot应用程序的配置类中注册我们的过滤器。可以通过使用@Bean注解将过滤器类声明为一个bean,并将其添加到Spring Boot应用程序的过滤器链中。这将确保在请求到达控制器之前,我们的过滤器将被调用。 最后,我们可以通过在配置类中使用@Order注解来指定过滤器的执行顺序。如果有多个过滤器,根据需要可以使用不同的顺序来执行它们。 总的来说,Spring Boot通过实现javax.servlet.Filter接口和在配置类中注册过滤器的方式来实现过滤器。通过编写逻辑代码并将过滤器添加到过滤器链中,我们可以在请求进入Web应用程序之前或之后进行一些自定义操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

54hake

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值