瀏覽代碼

自定义ShiroFilterFactoryBean防止中文请求被拦截

RuoYi 3 年之前
父節點
當前提交
19803715be

+ 2 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java

@@ -28,6 +28,7 @@ import com.ruoyi.common.utils.spring.SpringUtils;
 import com.ruoyi.framework.shiro.realm.UserRealm;
 import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
 import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
+import com.ruoyi.framework.shiro.web.CustomShiroFilterFactoryBean;
 import com.ruoyi.framework.shiro.web.filter.LogoutFilter;
 import com.ruoyi.framework.shiro.web.filter.captcha.CaptchaValidateFilter;
 import com.ruoyi.framework.shiro.web.filter.kickout.KickoutSessionFilter;
@@ -266,7 +267,7 @@ public class ShiroConfig
     @Bean
     public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
     {
-        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
+        CustomShiroFilterFactoryBean shiroFilterFactoryBean = new CustomShiroFilterFactoryBean();
         // Shiro的核心安全接口,这个属性是必须的
         shiroFilterFactoryBean.setSecurityManager(securityManager);
         // 身份认证失败,则跳转到登录页面的配置

+ 85 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/CustomShiroFilterFactoryBean.java

@@ -0,0 +1,85 @@
+package com.ruoyi.framework.shiro.web;
+
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.filter.InvalidRequestFilter;
+import org.apache.shiro.web.filter.mgt.DefaultFilter;
+import org.apache.shiro.web.filter.mgt.FilterChainManager;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
+import org.apache.shiro.web.mgt.WebSecurityManager;
+import org.apache.shiro.web.servlet.AbstractShiroFilter;
+import org.apache.shiro.mgt.SecurityManager;
+import org.springframework.beans.factory.BeanInitializationException;
+import javax.servlet.Filter;
+import java.util.Map;
+
+/**
+ * 自定义ShiroFilterFactoryBean解决资源中文路径问题
+ * 
+ * @author ruoyi
+ */
+public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean
+{
+    @Override
+    public Class<MySpringShiroFilter> getObjectType()
+    {
+        return MySpringShiroFilter.class;
+    }
+
+    @Override
+    protected AbstractShiroFilter createInstance() throws Exception
+    {
+
+        SecurityManager securityManager = getSecurityManager();
+        if (securityManager == null)
+        {
+            String msg = "SecurityManager property must be set.";
+            throw new BeanInitializationException(msg);
+        }
+
+        if (!(securityManager instanceof WebSecurityManager))
+        {
+            String msg = "The security manager does not implement the WebSecurityManager interface.";
+            throw new BeanInitializationException(msg);
+        }
+
+        FilterChainManager manager = createFilterChainManager();
+        // Expose the constructed FilterChainManager by first wrapping it in a
+        // FilterChainResolver implementation. The AbstractShiroFilter implementations
+        // do not know about FilterChainManagers - only resolvers:
+        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
+        chainResolver.setFilterChainManager(manager);
+
+        Map<String, Filter> filterMap = manager.getFilters();
+        Filter invalidRequestFilter = filterMap.get(DefaultFilter.invalidRequest.name());
+        if (invalidRequestFilter instanceof InvalidRequestFilter)
+        {
+            // 此处是关键,设置false跳过URL携带中文400,servletPath中文校验bug
+            ((InvalidRequestFilter) invalidRequestFilter).setBlockNonAscii(false);
+        }
+        // Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
+        // FilterChainResolver. It doesn't matter that the instance is an anonymous inner class
+        // here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
+        // injection of the SecurityManager and FilterChainResolver:
+        return new MySpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
+    }
+
+    private static final class MySpringShiroFilter extends AbstractShiroFilter
+    {
+        protected MySpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver)
+        {
+            if (webSecurityManager == null)
+            {
+                throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
+            }
+            else
+            {
+                this.setSecurityManager(webSecurityManager);
+                if (resolver != null)
+                {
+                    this.setFilterChainResolver(resolver);
+                }
+            }
+        }
+    }
+}