struts2 <allowed-methods > 標簽配置
1.在struts2 2.5版本中添加了對方法訪問的權限,如果沒有被添加到<allow-method> 方法的標簽,將會報一下錯誤
5:05:18.078 [http-apr-8020-exec-8] ERROR org.apache.struts2.dispatcher.Dispatcher - Could not find action or result: /core/DayFirst!login.do com.opensymphony.xwork2.config.ConfigurationException: Method login for action DayFirst is not allowed!at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:203) ~[struts2-core-2.5.14.1.jar:?] at com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:76) ~[struts2-core-2.5.14.1.jar:?] at org.apache.struts2.rest.RestActionProxyFactory.createActionProxy(RestActionProxyFactory.java:50) ~[struts2-rest-plugin-2.5.14.1.jar:?] at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:564) [struts2-core-2.5.14.1.jar:?] at org.apache.struts2.dispatcher.ExecuteOperations.executeAction(ExecuteOperations.java:79) [struts2-core-2.5.14.1.jar:?] at org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:141) [struts2-core-2.5.14.1.jar:?] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.73] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.73] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218) [catalina.jar:7.0.73] at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:122) [catalina.jar:7.0.73] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java) [catalina.jar:7.0.73] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) [catalina.jar:7.0.73] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) [catalina.jar:7.0.73] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [catalina.jar:7.0.73] at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:958) [catalina.jar:7.0.73] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.73] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:452) [catalina.jar:7.0.73] at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1087) [tomcat-coyote.jar:7.0.73] at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637) [tomcat-coyote.jar:7.0.73] at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2517) [tomcat-coyote.jar:7.0.73] at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2506) [tomcat-coyote.jar:7.0.73] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [?:1.7.0_79] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [?:1.7.0_79] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.73] at java.lang.Thread.run(Thread.java:745) [?:1.7.0_79]
解決方法:在struts2 的配置文件中加上<allowed-methods >regex:*</allowed-methods>即可。配置文件如下
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <constant name="struts.i18n.encoding" value="UTF-8"/> <constant name="struts.action.extension" value="do"/> <constant name="struts.devMode" value="true"/> <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant> <package name="core" namespace="/core" extends="struts-default"> <action name="*.*" class="com.controller.{1}Action" method="{2}"> <result name="success" >/WEB-INF/view/success.jsp</result> <!--這個配置是修復struts的漏洞--> <allowed-methods >regex:*</allowed-methods> </action> </package> </struts>
當然問題是解決了,看著也很簡單就是正則表達式,但是struts2 的原理是什麽為什麽要這麽做?
1.struts2 為什麽要對訪問的方法加以控制?查看這篇文章就了解了http://www.freebuf.com/vuls/128668.html
2.分析怎麽解決這個問題的。首先在控制臺查看異常,最先出現異常的類先打印,所以直接看第一行的異常DefaultActionProxy.java:203 ,找到如下地方
配置文件是在server容器啟動時候就開始執行了,為什麽會這樣,是因為配置文件的初始化放在struts2 的strutsPrepareAndExcuteFilter 的init() 方法中。再看this.config.isAllowedMethod 這個方法是判斷傳入進來的方法是否在配置文件中有。
this.allowedMethods.isAllowed(method) 這個類的這個方法控制了action 方法的訪問權限
查看AllowedMethod 這個類,<Allowed-method> 標簽是怎麽被解析的
public static AllowedMethods build(boolean strictMethodInvocation, Set<String> methods, String defaultRegex) { Set<AllowedMethods.AllowedMethod> allowedMethods = new HashSet(); Iterator i$ = methods.iterator(); while(true) { while(i$.hasNext()) { String method = (String)i$.next(); boolean isPattern = false; StringBuilder methodPattern = new StringBuilder(); int len = method.length(); for(int x = 0; x < len; ++x) { char c = method.charAt(x); if (x < len - 2 && c == ‘{‘ && ‘}‘ == method.charAt(x + 2)) { methodPattern.append(defaultRegex); isPattern = true; x += 2; } else { methodPattern.append(c); } } if (isPattern && !method.startsWith("regex:") && !strictMethodInvocation) { allowedMethods.add(new AllowedMethods.PatternAllowedMethod(methodPattern.toString(), method)); } else { String pattern; if (method.startsWith("regex:")) { pattern = method.substring(method.indexOf(":") + 1); allowedMethods.add(new AllowedMethods.PatternAllowedMethod(pattern, method)); } else if (method.contains("*") && !method.startsWith("regex:") && !strictMethodInvocation) { pattern = method.replace("*", defaultRegex); allowedMethods.add(new AllowedMethods.PatternAllowedMethod(pattern, method)); } else if (!isPattern) { allowedMethods.add(new AllowedMethods.LiteralAllowedMethod(method)); } else { LOG.trace("Ignoring method name: [{}] when SMI is set to [{}]", method, strictMethodInvocation); } } } LOG.debug("Defined allowed methods: {}", allowedMethods); return new AllowedMethods(strictMethodInvocation, allowedMethods, defaultRegex); } }
大致的意思就是, 將<allowed-method> 標簽的內容放入allowedMethods 這個set 集合中,以便調用action 的方法時候決定這個action的方法是否可以被調用。
這裏的放入規則遵循標紅的判斷,帶有regex: 前綴的,帶有* 的將被單獨處理,就是將所有的方法都通過。
看上面的debug 圖,發現struts2 默認帶了一些有權限的方法 index input 等。
最後還有 <global-allowed-methods>regex:.*</global-allowed-methods> 標簽也可以解決問題。
struts2 <allowed-methods > 標簽配置