Skip to content

Instantly share code, notes, and snippets.

@838239178
Last active February 7, 2024 08:11
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 838239178/f20507ea330a199bec5f8da183a24dc2 to your computer and use it in GitHub Desktop.
Save 838239178/f20507ea330a199bec5f8da183a24dc2 to your computer and use it in GitHub Desktop.
Shiro支持中文的InvalidRequstFilter
package group.java.campusmall.shiro;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.filter.InvalidRequestFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
@Component
public class CNInvalidRequestFilter extends AccessControlFilter {
private static final List<String> SEMICOLON = Collections.unmodifiableList(Arrays.asList(";", "%3b", "%3B"));
private static final List<String> BACKSLASH = Collections.unmodifiableList(Arrays.asList("\\", "%5c", "%5C"));
private boolean blockSemicolon = true;
private boolean blockBackslash = !Boolean.getBoolean("org.apache.shiro.web.ALLOW_BACKSLASH");
private boolean blockNonAscii = true;
protected boolean isAccessAllowed(ServletRequest req, ServletResponse response, Object mappedValue) throws Exception {
HttpServletRequest request = WebUtils.toHttp(req);
return this.isValid(request.getRequestURI()) && this.isValid(request.getServletPath()) && this.isValid(request.getPathInfo());
}
private boolean isValid(String uri) {
return !StringUtils.hasText(uri) || !this.containsSemicolon(uri) && !this.containsBackslash(uri) && !this.containsNonAsciiCharacters(uri);
}
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
WebUtils.toHttp(response).sendError(400, "Invalid request");
return false;
}
private boolean containsSemicolon(String uri) {
if (this.isBlockSemicolon()) {
Stream<String> var10000 = SEMICOLON.stream();
Objects.requireNonNull(uri);
return var10000.anyMatch(uri::contains);
} else {
return false;
}
}
private boolean containsBackslash(String uri) {
if (this.isBlockBackslash()) {
Stream<String> var10000 = BACKSLASH.stream();
Objects.requireNonNull(uri);
return var10000.anyMatch(uri::contains);
} else {
return false;
}
}
private boolean containsNonAsciiCharacters(String uri) {
if (this.isBlockNonAscii()) {
return !containsOnlyPrintableAsciiCharacters(uri);
} else {
return false;
}
}
private boolean isChinese(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION;
}
private boolean containsOnlyPrintableAsciiCharacters(String uri) {
int length = uri.length();
for(int i = 0; i < length; ++i) {
char c = uri.charAt(i);
if ((c < ' ' || c > '~') && !isChinese(c)) {
return false;
}
}
return true;
}
public boolean isBlockSemicolon() {
return this.blockSemicolon;
}
public void setBlockSemicolon(boolean blockSemicolon) {
this.blockSemicolon = blockSemicolon;
}
public boolean isBlockBackslash() {
return this.blockBackslash;
}
public void setBlockBackslash(boolean blockBackslash) {
this.blockBackslash = blockBackslash;
}
public boolean isBlockNonAscii() {
return this.blockNonAscii;
}
public void setBlockNonAscii(boolean blockNonAscii) {
this.blockNonAscii = blockNonAscii;
}
}
@838239178
Copy link
Author

InvalidRequestFilter的代码复制下下来完全重写,其实只改变方法 containsOnlyPrintableAsciiCharacters 在判断中加入中文字符的检测,防止误杀 !!!

@lengqie
Copy link

lengqie commented May 12, 2021

LGTM!!!终于找到解决方案了!!

@838239178
Copy link
Author

LGTM!!!终于找到解决方案了!!

很高兴能帮到你!要不点个:star:Star在走吧 [doge]

@838239178
Copy link
Author

838239178 commented May 13, 2021

配置该过滤器的方法请到这里来

@shuangovo
Copy link

排查半天才知道是Shiro的问题,感谢大佬给出解决方案

@chanchaw
Copy link

我是新手,弱弱的问下,要怎么把这个自定义的 filter 替换掉默认的 filter ?

@838239178
Copy link
Author

我是新手,弱弱的问下,要怎么把这个自定义的 filter 替换掉默认的 filter ?

看楼上我发的啊,如果进不去要挂加速器

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment