【Spring Security】使用 OncePerRequestFilter 过滤器校验登录过期、请求日志等操作

文章介绍了如何在SpringSecurity框架中使用OncePerRequestFilter实现登录过期检查和操作日志记录,同时配置了SecurityConfiguration以管理鉴权和过滤器顺序。
摘要由CSDN通过智能技术生成


前言

OncePerRequestFilter 是一个过滤器,每个请求都会执行一次;一般开发中主要是做检查是否已登录、Token是否过期和授权等操作,而每个操作都是一个过滤器,下面演示一下。


OncePerRequestFilter 使用

检查是否登录过期过滤器

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 检查是否登录过期
 *
 * @author francis
 * @create: 2023-08-30 16:45
 **/
@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.info("进入 JwtAuthenticationTokenFilter ...");
        /**
         * 从 request 的 header 中拿出来 token
         */

        String token = request.getHeader("token");
        if (token == null || token.isEmpty()) {
            // 没有携带 token 则 放行
            filterChain.doFilter(request, response);
            return;
        }

        /**
         * 检查 token 是否过期逻辑 .....
         */
        // 放行
        filterChain.doFilter(request, response);
    }
}

检查是否登录过期过滤器

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 请求日志
 *
 * @author francis
 * @create: 2023-08-31 10:15
 **/
@Component
@Slf4j
public class OperationLogFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.info("OperationLogFilter ...");
        /**
         * 操作日志记录 ...
         */
        // 放行
        filterChain.doFilter(request, response);
    }

}

SecurityConfiguration 配置


import com.security.filter.JwtAuthenticationTokenFilter;
import com.security.filter.OperationLogFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Security 配置类
 *
 * @author francis
 * @create: 2023-08-30 14:19
 **/
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    private OperationLogFilter operationLogFilter;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // 关闭csrf
                .csrf().disable()
                // 不通过 Session 获取 SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                    .authorizeRequests()
                        // 对于登录接口 允许匿名访问
                        .antMatchers("/login")
                            .permitAll()
                        // 除上面外的所有请求全部需要鉴权认证
                        .anyRequest()
                            .authenticated();

        // 在 UsernamePasswordAuthenticationFilter(验证用户) 之前执行
        // TODO 需要注意的是下面过滤器的顺序就是执行的顺序,使用 @Order 也没办法改变
        http
        		// 登录是否过期
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
                // 请求日志
                .addFilterBefore(operationLogFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}




End


Spring Security中,可以使用过滤器来检查token是否过期。具体实现步骤如下: 1. 创建一个继承自`OncePerRequestFilter`的过滤器,用于检查token是否过期: ```java public class JwtTokenAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String token = extractToken(request); // 检查token是否过期,如果过期则返回错误信息 if (isTokenExpired(token)) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token has expired"); return; } chain.doFilter(request, response); } private boolean isTokenExpired(String token) { // 解析token获取过期时间 Date expiration = getExpirationDateFromToken(token); // 检查当前时间是否晚于过期时间 return expiration.before(new Date()); } private String extractToken(HttpServletRequest request) { // 从请求头或请求参数中获取token String bearerToken = request.getHeader("Authorization"); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } return request.getParameter("token"); } private Date getExpirationDateFromToken(String token) { // 解析token获取过期时间 return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getExpiration(); } } ``` 2. 在Spring Security配置中将该过滤器添加到过滤器链中: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtTokenAuthenticationFilter jwtTokenAuthenticationFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/authenticate").permitAll() .anyRequest().authenticated() .and() .addFilterBefore(jwtTokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); } } ``` 这样,当请求经过该过滤器时,将会检查token是否过期,并在token过期时返回错误信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值