若依加入自己的过滤器
三个步骤完成过滤器自定义添加第一步在自己模块下创建想要的过滤器编写自己的过滤器packagecom.ruoyi.agriculture.filter;importcom.fasterxml.jackson.databind.ObjectMapper;importcom.ruoyi.agriculture.domain.WxGKUser;importcom.ruoyi.agriculture.mapper.WxGKUserMapper;importjakarta.servlet.FilterChain;importjakarta.servlet.ServletException;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.core.Ordered;importorg.springframework.core.annotation.Order;importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.security.authentication.UsernamePasswordAuthenticationToken;importorg.springframework.security.core.context.SecurityContextHolder;importorg.springframework.security.web.authentication.WebAuthenticationDetailsSource;importorg.springframework.stereotype.Component;importorg.springframework.util.StringUtils;importorg.springframework.web.filter.OncePerRequestFilter;importjava.io.IOException;importjava.util.concurrent.TimeUnit;/** * 微信小程序认证过滤器 * 专门处理微信小程序的token验证 */Order(85)// 使用Order注解指定顺序值越小越先执行ComponentpublicclassGKWxAuthFilterextendsOncePerRequestFilterimplementsOrdered{OverridepublicintgetOrder(){System.out.println(GKWxAuthFilter 执行URI);return85;}// Redis中微信token的前缀用于与系统其他token区分privatestaticfinalStringGK_TOKEN_PREFIXwx_Token:;// 微信小程序接口的基础路径用于过滤需要处理的请求privatestaticfinalStringGK_API_PREFIX/wx/;// Jackson的JSON处理工具Spring默认已集成privatestaticfinalObjectMapperobjectMappernewObjectMapper();AutowiredprivateStringRedisTemplatestringRedisTemplate;AutowiredprivateWxGKUserMapperwxGKUserMapper;// 移除原writeErrorResponse方法替换为抛出异常OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainfilterChain)throwsServletException,IOException{System.out.println(GKWxAuthFilter 执行URIrequest.getRequestURI());if(request.getRequestURI().startsWith(GK_API_PREFIX)){StringgkTokenrequest.getHeader(wx-token);if(isPublicWxApi(request.getRequestURI())){filterChain.doFilter(request,response);return;}// 验证token是否存在if(!StringUtils.hasText(gkToken)){thrownewGKWxAuthenticationException(微信登录凭证不存在请重新登录);}// 从Redis获取用户IDStringuserIdStrstringRedisTemplate.opsForValue().get(GK_TOKEN_PREFIXgkToken);if(!StringUtils.hasText(userIdStr)){thrownewGKWxAuthenticationException(微信登录凭证已过期请重新登录);}// 刷新token有效期stringRedisTemplate.expire(GK_TOKEN_PREFIXgkToken,7,TimeUnit.DAYS);// 查询用户信息LonguserId;try{userIdLong.parseLong(userIdStr);}catch(NumberFormatExceptione){thrownewGKWxAuthenticationException(用户ID格式错误);}WxGKUseruserwxGKUserMapper.selectById(userId);if(usernull){thrownewGKWxAuthenticationException(用户不存在);}// 设置认证信息UsernamePasswordAuthenticationTokenauthenticationnewUsernamePasswordAuthenticationToken(user,null,null);authentication.setDetails(newWebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authentication);}filterChain.doFilter(request,response);}/** * 判断是否为微信公开接口 */privatebooleanisPublicWxApi(StringrequestUri){returnrequestUri.startsWith(/wx/user/login)||requestUri.startsWith(/wx/user/register)||requestUri.startsWith(/wx/user/privacy);}}定义的异常类packagecom.ruoyi.agriculture.filter;importorg.springframework.security.core.AuthenticationException;publicclassGKWxAuthenticationExceptionextendsAuthenticationException{publicGKWxAuthenticationException(Stringmsg){super(msg);}// public GkWxAuthenticationException(String msg, Throwable cause) {// super(msg, cause);// }}第二步在framework模块下操作记得要把自己的模块引入com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java 找到若依自己的过滤器在里面进行一些修改 对微信接口直接放行不进行JWT验证packagecom.ruoyi.framework.security.filter;importjava.io.IOException;importjakarta.servlet.FilterChain;importjakarta.servlet.ServletException;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.core.Ordered;importorg.springframework.core.annotation.Order;importorg.springframework.security.authentication.UsernamePasswordAuthenticationToken;importorg.springframework.security.core.context.SecurityContextHolder;importorg.springframework.security.web.authentication.WebAuthenticationDetailsSource;importorg.springframework.stereotype.Component;importorg.springframework.web.filter.OncePerRequestFilter;importcom.ruoyi.common.core.domain.model.LoginUser;importcom.ruoyi.common.utils.SecurityUtils;importcom.ruoyi.common.utils.StringUtils;importcom.ruoyi.framework.web.service.TokenService;/** * token过滤器 验证token有效性 * * author ruoyi */Order(90)// JWT过滤器顺序应在微信过滤器之后ComponentpublicclassJwtAuthenticationTokenFilterextendsOncePerRequestFilterimplementsOrdered{AutowiredprivateTokenServicetokenService;OverridepublicintgetOrder(){return90;}OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainchain)throwsServletException,IOException{System.out.println(JwtAuthenticationTokenFilter 构造方法被调用);// 对微信接口直接放行不进行JWT验证if(request.getRequestURI().startsWith(/wx/)){chain.doFilter(request,response);return;}LoginUserloginUsertokenService.getLoginUser(request);if(StringUtils.isNotNull(loginUser)StringUtils.isNull(SecurityUtils.getAuthentication())){tokenService.verifyToken(loginUser);UsernamePasswordAuthenticationTokenauthenticationTokennewUsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());authenticationToken.setDetails(newWebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authenticationToken);}chain.doFilter(request,response);}}第三步将这些接口放行后还需要对spring security配置进行修改将自己的过滤器注入到里面去packagecom.ruoyi.framework.config;importcom.ruoyi.agriculture.filter.GKWxAuthFilter;importcom.ruoyi.framework.security.filter.WxAuthFilter;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.CommandLineRunner;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.annotation.Order;importorg.springframework.http.HttpMethod;importorg.springframework.security.authentication.AuthenticationManager;importorg.springframework.security.authentication.ProviderManager;importorg.springframework.security.authentication.dao.DaoAuthenticationProvider;importorg.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.http.SessionCreationPolicy;importorg.springframework.security.core.userdetails.UserDetailsService;importorg.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;importorg.springframework.security.web.SecurityFilterChain;importorg.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;importorg.springframework.security.web.authentication.logout.LogoutFilter;importcom.ruoyi.framework.config.properties.PermitAllUrlProperties;importcom.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;importcom.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;importcom.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;importorg.springframework.core.Ordered;importorg.springframework.stereotype.Component;importorg.springframework.web.cors.CorsConfiguration;importorg.springframework.web.cors.CorsConfigurationSource;importorg.springframework.web.cors.UrlBasedCorsConfigurationSource;importstaticorg.springframework.security.config.Customizer.withDefaults;/** * spring security配置 * * author ruoyi */EnableMethodSecurity(prePostEnabledtrue,securedEnabledtrue)ConfigurationpublicclassSecurityConfig{/** * 自定义用户认证逻辑 */AutowiredprivateUserDetailsServiceuserDetailsService;/** * 认证失败处理类 */AutowiredprivateAuthenticationEntryPointImplunauthorizedHandler;/** * 退出处理类 */AutowiredprivateLogoutSuccessHandlerImpllogoutSuccessHandler;/** * token认证过滤器 */AutowiredprivateJwtAuthenticationTokenFilterauthenticationTokenFilter;AutowiredprivateWxAuthFilterwxAuthFilter;/** * 微信小程序专用认证过滤器 */AutowiredprivateGKWxAuthFiltergkWxAuthFilter;// 注入/** * 允许匿名访问的地址 */AutowiredprivatePermitAllUrlPropertiespermitAllUrl;/** * 身份验证实现 */BeanpublicAuthenticationManagerauthenticationManager(){DaoAuthenticationProviderdaoAuthenticationProvidernewDaoAuthenticationProvider();daoAuthenticationProvider.setUserDetailsService(userDetailsService);daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());returnnewProviderManager(daoAuthenticationProvider);}/** * anyRequest | 匹配所有请求路径 * access | SpringEl表达式结果为true时可以访问 * anonymous | 匿名可以访问 * denyAll | 用户不能访问 * fullyAuthenticated | 用户完全认证可以访问非remember-me下自动登录 * hasAnyAuthority | 如果有参数参数表示权限则其中任何一个权限可以访问 * hasAnyRole | 如果有参数参数表示角色则其中任何一个角色可以访问 * hasAuthority | 如果有参数参数表示权限则其权限可以访问 * hasIpAddress | 如果有参数参数表示IP地址如果用户IP和参数匹配则可以访问 * hasRole | 如果有参数参数表示角色则其角色可以访问 * permitAll | 用户可以任意访问 * rememberMe | 允许通过remember-me登录的用户访问 * authenticated | 用户登录后可访问 */BeanprotectedSecurityFilterChainfilterChain(HttpSecurityhttpSecurity)throwsException{returnhttpSecurity// 采用Spring Security6.x拥抱springboot3默认的CORS配置.cors(withDefaults())// CSRF禁用因为不使用session.csrf(csrf-csrf.disable())// 禁用HTTP响应标头.headers((headersCustomizer)-{headersCustomizer.cacheControl(cache-cache.disable()).frameOptions(options-options.sameOrigin());})// 认证失败处理类.exceptionHandling(exception-exception.authenticationEntryPoint(unauthorizedHandler))// 基于token所以不需要session.sessionManagement(session-session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))// 注解标记允许匿名访问的url.authorizeHttpRequests((requests)-{permitAllUrl.getUrls().forEach(url-requests.requestMatchers(url).permitAll());// 微信小程序接口配置requests.requestMatchers(/wx/user/login).permitAll()// 小程序登录允许匿名访问.requestMatchers(/wx/user/register).permitAll()// 小程序注册允许匿名访问.requestMatchers(/wx/user/privacy).permitAll()// 隐私政策允许匿名访问// 微信其他接口需要认证.requestMatchers(/wx/**).authenticated();// 对于登录login 注册register 验证码captchaImage 允许匿名访问requests.requestMatchers(/login,/register,/captchaImage).permitAll()// 静态资源可匿名访问.requestMatchers(HttpMethod.GET,/,/*.html,/**.html,/**.css,/**.js,/profile/**).permitAll().requestMatchers(/swagger-ui.html,/v3/api-docs/**,/swagger-ui/**,/druid/**).permitAll()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();}).logout(logout-logout.logoutUrl(/logout).logoutSuccessHandler(logoutSuccessHandler)).addFilterBefore(authenticationTokenFilter,UsernamePasswordAuthenticationFilter.class).addFilterBefore(gkWxAuthFilter,JwtAuthenticationTokenFilter.class).build();}/** * 强散列哈希加密实现 */BeanpublicBCryptPasswordEncoderbCryptPasswordEncoder(){returnnewBCryptPasswordEncoder();}/** * 跨域配置 * 允许跨域访问 * 允许所有请求 * 允许所有请求头 * 允许所有方法 * 允许所有请求源 * 允许所有请求路径 * */BeanpublicCorsConfigurationSourcecorsConfigurationSource(){CorsConfigurationconfigurationnewCorsConfiguration();configuration.addAllowedOriginPattern(*);configuration.addAllowedMethod(*);configuration.addAllowedHeader(*);configuration.setAllowCredentials(true);UrlBasedCorsConfigurationSourcesourcenewUrlBasedCorsConfigurationSource();source.registerCorsConfiguration(/**,configuration);returnsource;}}GKWxAuthFilter 就会正确加入到 Security 过滤器链中 /wx/ 请求会被它处理。