EasyJWeb的验证系统的Bug及使用心得

news/2024/11/8 14:22:49

 
   今天使用EasyJWeb的“人性化”验证功能,发现了存在不少Bug,这里发出来并与大家分享。

    我们系统中的User基类的内容如下:

 

@Entity
@Cache(usage 
=  CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@javax.persistence.Table(name 
=   " UserInfo " )
@Inheritance(strategy 
=  InheritanceType.JOINED)
@FormPO(inject 
=   " name,email,password,problem,solution " )
public   abstract   class  User  implements  Principal, UserDetails  {

 
private static final long serialVersionUID = 2915030721449148555L;

 @Id
 @GeneratedValue(strategy 
= GenerationType.TABLE)
 
private Long id;

 @Column(length 
= 30, unique = true)
 @Field(validator 
= @Validator(name = "string", value = "blank;trim;max:30", required = true))
 
private String name;

 @Column(length 
= 100)
 @Field(validator 
= @Validator(name = "email", required = true, value = "max:100"))
 
private String email;

 @Column(length 
= 64)
 @Field(validator 
= @Validator(name = "string", value = "blank;trim;max:64", required = true))
 
private String password;

 
private Date registerTime;

 
private Integer status = 1;// -1锁定、0未审核、1通过

 
private Integer loginTimes;

 
private Date lastLoginTime = new Date();

 
private String lastLoginIP;

 
private String problem; // 密码提问

 
private String solution; // 答案

 
private Long imUin;

 @ManyToMany(mappedBy 
= "users", cascade = CascadeType.ALL)
 @JoinTable(name 
= "User_Roles")
 
private List<Role> roles = new java.util.ArrayList<Role>();

 @ManyToMany(cascade 
= CascadeType.ALL)
 @JoinTable(name 
= "User_Permissions")
 
private List<Permission> permissions = new java.util.ArrayList<Permission>();

 @Transient
 
private GrantedAuthority[] authorities;

 ...

}


 

下面是一个User的子类,PersonalUser的内容如下:

 

@FormPO(label = " 个人用户信息 " ,disInject = " score,activeCode " )
@Entity
@Cache(usage 
=  CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public   class  PersonalUser  extends  User  {
 
/**
  * 积分
  
*/

 
private Integer score;

 
/**
  * 真实姓名
  
*/

 @Field(name
="真实姓名", validators = { @Validator(name = "string", value = "msg:请填写您的真实姓名。;blank;min:2;max:10", required = true) })
 @Column(length 
= 20)
 
private String trueName;

 
/**
  * 身份证号
  
*/

 @Field(name
="身份证号", validators = { @Validator(name="regex",value="msg:请填写有效的证件号码。;expression:/d{15}|/d{17}[/dXx]", required = true) })
 @Column(length 
= 20)
 
private String identifyCard;

 
/**
  * 电话
  
*/

 @Field(name
="电话", validators = { @Validator(name = "required", value = "msg:您填写的身份证号码有误,请检查后重新提交。;blank;min:7;max:15", required = true) })
 @Column(length 
= 20)
 
private String tel;

 
/**
  * 手机
  
*/

 @Field(name
="手机", validators = { @Validator(name = "regex", value = "expression:/d{11}", required = true) })
 @Column(length 
= 25)
 
private String mobile;

..
}


 

下面是个人用户注册保存时的源代码:

 

/**
  * 保存个人注册信息
  * 
  * 
@param form
  * 
@return
  
*/

 
public  Page savePersonal(WebForm form)  {  
  PersonalUser user 
= form.toPo(PersonalUser.class);
  
if(hasErrors())return page("registerStep3Personal");//跳回注册页面
  
//执行注册操作
  this.userService.addPersonalUser(user);
  
return page("success");
 }



    执行这个程序,针对name及password等属性的验证能正常工作。但PersonalUser中针对电话号码、身份证等属性无论如何都不能正常执行验证功能,真是郁闷啊。后来仔细发现,不但没有执行验证,尽然连值也没有传入到持久层中。因此,应该是不允许注入这些属性值的问题所允许的。于是跟踪了一下源代码,在com.easyjf.web.core.FormHandler中发现如下的内容:

 

public   boolean  checkFormPOWriteEnabled(Class clz,
            java.beans.PropertyDescriptor property) 
{
        
boolean ret = true;
        FormPO formPO 
= (FormPO) clz.getAnnotation(FormPO.class);
        
boolean haveFound = false;
        
if (formPO != null{
            String injectEnabled 
= formPO.inject();
            
            
if (StringUtils.hasLength(injectEnabled)) {
                ret 
= ("," + injectEnabled + ",").indexOf(","
                        
+ property.getName() + ",">= 0;// 找不到,则不注入
                if (ret)
                    haveFound 
= true;
            }
 else {
                String disInject 
= formPO.disInject();                
                
if (StringUtils.hasLength(disInject))
                    ret 
= ("," + disInject + ",").indexOf(","
                            
+ property.getName() + ","< 0;// 找到,则不注入
                if (!ret)
                    haveFound 
= true;
            }
        
        }

        
if (!haveFound && clz.getSuperclass() != Object.class)
            ret 
= checkFormPOWriteEnabled(clz.getSuperclass(), property);
        
return ret;
    }


   

     这个方法写得比较有意思,几行代码转了几个弯,真考验人的逻辑思维啊。他是在检查@FormPO标签中的inject或disInject属性情况。在子类中若找不到标签属性,还会到父类中去找。感觉这里问题就出来了,如果父类跟子类使用的注入指标标签不一致的话,应该就会出现问题。也就是说如果父类中使用inject来标签注入的属性,而子类中使用disInject来指定不可以注入的属性。则先在子类中发现这个属性没找到,则haveFound就为false,则到父类中去找,由于父类使用inject标识,而一般他不会把子类的属性也标识进去,所以肯定得到的结果也是false。因此,就会给我们无法注入的结果。
    这应该是跟子类中想要表达的意思不一致:“也即子类规定的是除了disInject中规定的属性以外(或者是所有属性,即inject及disInject都没有用的情况下)的所有属性都可以注入”这一功能无法实现。
 
    这不知道算不算上是一个Bug。但想了一下,这个Bug也可以完全避免,只要把父类及子类的注入标识写一致就OK了。于是我把两者的注入标识都改成了使用disInject属性。如下:

正常的User基类

 

@FormPO(disInject  =   " id,status,loginTimes,lastLoginTime,lastLoginIP,roles,permissions,authorities " )
public   abstract   class  User  implements  Principal, UserDetails  {

 ...

}


 

 子类PersonalUser

 

@FormPO(label = " 个人用户信息 " ,disInject = " score " )
public   class  PersonalUser  extends  User  {

..
}

 

    然后执行刚才的用户注册程序,验证系统终于“人性化”地按我要的出来了。呵呵,大功告成,立即走人。


 





http://www.niftyadmin.cn/n/3648095.html

相关文章

如何使用Docker,Nginx和加密来扩展和保护Django应用程序

介绍 (Introduction) In cloud-based environments, there are multiple ways to scale and secure a Django application. By scaling horizontally, and running several copies of your app, you can build a more fault-tolerant and highly-available system, while also …

EasyJF开源团队欢迎您的加入

您想玩转JavaEE领域里最前沿的技术吗&#xff1f;您想与一群来自大江南北的技术狂热爱好者成为朋友吗&#xff1f;您愿意让您的代码、知识传播到世界每一个需要程序及程序员的角落吗&#xff1f;您想认识一群长期蜷伏在开源社区中各大中型软件公司的技术掌门人吗&#xff1f;您…

如何在Ubuntu 20.04上安装Elasticsearch,Logstash和Kibana(弹性堆栈)

介绍 (Introduction) The Elastic Stack — formerly known as the ELK Stack — is a collection of open-source software produced by Elastic which allows you to search, analyze, and visualize logs generated from any source in any format, a practice known as cen…

使用Mylyn插件管理bug

今天使用Jira的时候遇到一些问题&#xff0c;搜索的时候无意中发现有一个插件Mylyn可以管理Jira中的bug&#xff0c;于是装了一个。弄了一下午&#xff0c;终于可以使用了。现在把安装的过程写下来&#xff0c;或许对大家有用。第一步&#xff0c;当然是下载插件了。下载地址&a…

如何在Ubuntu 20.04上使用Docker和Caddy远程访问GUI应用程序

介绍 (Introduction) Even with the growing popularity of cloud services, the need for running native applications still exists. 即使云服务越来越流行&#xff0c;仍然需要运行本机应用程序。 By using noVNC and TigerVNC, you can run native applications inside a…

EasyJF与Cownew携手打造BlueFin

作为国内两个比较活跃的开源团队&#xff0c;EasyJF及CowNew都在各自所专注的领域里为开源社区作了不少的贡献。EasyJF开源的EasyJWeb已经推出了1.0m1正式版本&#xff0c;并通过在国内多个大中型项目中的成功应用&#xff0c;充分证明了EasyJWeb是一个优秀并适合快速开发JavaW…

零配置及惯例代替配置

这是[挑战MVC极限]EasyJWeb-1.0特性的第四篇文章&#xff0c;今天主要介绍零配置及惯例代替配置。配置是好还是坏首先&#xff0c;我承认配置是好东西&#xff0c;它能够通过修改程序以外的数据来改变系统的运行性质或功能&#xff0c;大大提高了系统的灵活性&#xff0c;可维护…

如何在Ubuntu 18.04上将Postfix安装和配置为仅发送SMTP服务器

介绍 (Introduction) Postfix is a mail transfer agent (MTA), an application used to send and receive email. It can be configured so that it can be used to send emails by local application only. This is useful in situations when you need to regularly send em…