|
All Input Is Evil! -Writing secure code |
转换与校验(Conversion & Validation)
import java.util.Locale;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
public class HelloWorld extends ActionSupport {
private String msg;
private Locale loc = Locale.US;
public String getMsg() {
return msg;
}
public Locale getLoc() {
return loc;
}
public void setLoc(Locale loc) {
this .loc = loc;
}
@Override
public void validate() {
System.out.println( " Calling validate() " );
if ( ! (loc.equals(Locale.US) || loc.equals(Locale.CHINA))) {
addFieldError( " loc " , getText( " validation.loc " ));
}
}
public void validateExecute() {
System.out.println( " Calling validateExecute() by reflection " );
}
@Override
public String execute() {
System.out.println( " Calling execute() " );
// LocalizedTextUtil是Struts 2.0中国际化的工具类,<s:text>标志就是通过调用它实现国际化的
msg = LocalizedTextUtil.findDefaultText( " HelloWorld " , loc);
return SUCCESS;
}
}
< result > /HelloWorld.jsp </ result >
< result name ="input" > /HelloWorld.jsp </ result >
</ action >
<% @taglib prefix = " s " uri = " /struts-tags " %>
< html >
< head >
< title > Hello World </ title >
</ head >
< body >
< div style ="color:red;" >
< s:fielderror />
</ div >
< s:form action ="HelloWorld" theme ="simple" >
Locale: < s:textfield name ="loc" /> < s:submit />
</ s:form >
< h2 >< s:property value ="msg" /></ h2 >
</ body >
</ html >
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
public class LocaleConverter extends ognl.DefaultTypeConverter {
@Override
public Object convertValue(Map context, Object value, Class toType) {
if (toType == Locale. class ) {
System.out.println( " Converting String to Locale " );
String locale = ((String[]) value)[ 0 ];
return new Locale(locale.substring( 0 , 2 ), locale.substring( 3 ));
} else if (toType == String. class ) {
System.out.println( " Converting Locale to String " );
Locale locale = (Locale) value;
return locale.toString();
}
return null ;
}
}
invalid.fieldvalue.loc = Locale必须为\ " xx_XX\ " 的格式
validation.loc = 区域必须为中国或美国
invalid.fieldvalue.loc = Locale must like \ " xx_XX\ "
validation.loc = Locale must be China or USA
Calling validateExecute() by reflection...
Calling validate()...
Calling execute()...
Converting Locale to String...
- 通过转换器将请求参数转换成相应的Bean属性;
- 判断转换过程是否出现异常。如果有,则将其保存到ActionContext中,conversionError拦截器再封装为fieldError;如果没有,进行下一步;
- 通过反射(Reflection)来调用validateXxx()方法(其中,Xxx表示Action的方法名);
- 调用validate()方法;
- 如果经过上述步骤没有出现fieldError,则调用Action方法;如果有,则会跳过Action方法,通过国际化将fieldError输出到页面。
图1 校验顺序图
- 如果需要转换的数据,通常做法在转换的时候做格式的校验,在Action中的校验方法中校验取值。假如用户填错了格式,我们可以通过在资源文件配置invalid.fieldvalue.xxx(xxx为属性名)来提示用户正确的格式,不同的阶段出错显示不同的信息。具体做法请参考上面的例子;
- 至于用validate()还是validateXxx(),我推荐使用validate()。原因是validateXxx()使用了反射,相对来说性能稍差,而validate()则是通过接口com.opensymphony.xwork2.Validateable调用。当然如果你的表单数据取值是取决于特定Action方法,则应该使用validateXxx()。
图2 错误格式
图3 取值错误
使用Struts 2.0的校验框架
import com.opensymphony.xwork2.ActionSupport;
public class ValidationAction extends ActionSupport {
private String reqiuredString;
public String getReqiuredString() {
return reqiuredString;
}
public void setReqiuredString(String reqiuredString) {
this .reqiuredString = reqiuredString;
}
@Override
public String execute() {
return SUCCESS;
}
}
< result > /Output.jsp </ result >
< result name ="input" > /Input.jsp </ result >
</ action >
<% @taglib prefix = " s " uri = " /struts-tags " %>
< html >
< head >
< title > Hello World </ title >
<!-- 此标志的作用是引入Struts 2.0的常用的Javascript和CSS -->
< s:head />
</ head >
< body >
< s:form action ="ValidationAction" >
< s:textfield name ="reqiuredString" label ="Required String" />
< s:submit />
</ s:form >
</ body >
</ html >
<% @taglib prefix = " s " uri = " /struts-tags " %>
< html >
< head >
< title > Hello World </ title >
</ head >
< body >
Required String: < s:property value ="reqiuredString" />
</ body >
</ html >
<! DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd" >
< validators >
< field name ="reqiuredString" >
< field-validator type ="requiredstring" >
< message > This string is required </ message >
</ field-validator >
</ field >
</ validators >
图4 Input.jsp
图5 错误提示
图6 Output.jsp
- 还没有国际化错误消息;
- 没有实现客户端的校验。
- 在Xxx-validation.xml文件中的<message>元素中加入key属性;
- 在Input.jsp中的<s:form>标志中加入validate="true"属性,就可以在用Javascript在客户端校验数据。
图7 客户端校验
配置文件查找顺序
- 接口 Animal;
- 接口 Quadraped 扩展了 Animal;
- 类 AnimalImpl 实现了 Animal;
- 类 QuadrapedImpl 扩展了 AnimalImpl 实现了 Quadraped;
- 类 Dog 扩展了 QuadrapedImpl;
- Animal-validation.xml
- Animal-别名-validation.xml
- AnimalImpl-validation.xml
- AnimalImpl-别名-validation.xml
- Quadraped-validation.xml
- Quadraped-别名-validation.xml
- QuadrapedImpl-validation.xml
- QuadrapedImpl-别名-validation.xml
- Dog-validation.xml
- Dog-别名-validation.xml
已有的校验器
< validator name ="required" class ="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator" />
< validator name ="requiredstring" class ="com.opensymphony.xwork2.validator.validators.RequiredStringValidator" />
< validator name ="int" class ="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator" />
< validator name ="double" class ="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator" />
< validator name ="date" class ="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator" />
< validator name ="expression" class ="com.opensymphony.xwork2.validator.validators.ExpressionValidator" />
< validator name ="fieldexpression" class ="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator" />
< validator name ="email" class ="com.opensymphony.xwork2.validator.validators.EmailValidator" />
< validator name ="url" class ="com.opensymphony.xwork2.validator.validators.URLValidator" />
< validator name ="visitor" class ="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator" />
< validator name ="conversion" class ="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator" />
< validator name ="stringlength" class ="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator" />
< validator name ="regex" class ="com.opensymphony.xwork2.validator.validators.RegexFieldValidator" />
</ validators >
关于每个校验器的具体用法,请参考以下链接: [url]http://wiki.javascud.org/display/ww2cndoc/Validation[/url] 该链接中还有一些很有的信息,请大家仔细阅读。 |
总结
|