Ibm mobilefirst MobileFirst 8:存储数据时遇到意外错误

Ibm mobilefirst MobileFirst 8:存储数据时遇到意外错误,ibm-mobilefirst,mobilefirst-adapters,Ibm Mobilefirst,Mobilefirst Adapters,我们正在使用UserAuthenticationSecurityCheck对用户进行身份验证 如果验证成功,MFP服务器将存储用户属性 public class AuthSecurityCheck extends UserAuthenticationSecurityCheck { static Logger logger = Logger.getLogger(AuthSecurityCheck.class.getName()); private String userId,

我们正在使用UserAuthenticationSecurityCheck对用户进行身份验证

如果验证成功,MFP服务器将存储用户属性

public class AuthSecurityCheck extends UserAuthenticationSecurityCheck {

    static Logger logger = Logger.getLogger(AuthSecurityCheck.class.getName());

    private String userId, displayName;
    private JSONObject attrObject;

    private String errorMessage;

    @Override
    protected AuthenticatedUser createUser() {
        Map<String, Object> userAttrsMap = new HashMap<String, Object>();
        userAttrsMap.put("attributes",attrObject); 
        return new AuthenticatedUser(userId, displayName, this.getName(), userAttrsMap);
    }
...
}
公共类AuthSecurityCheck扩展了UserAuthenticationSecurityCheck{
静态记录器Logger=Logger.getLogger(AuthSecurityCheck.class.getName());
私有字符串userId,displayName;
私有JSONObject属性对象;
私有字符串错误消息;
@凌驾
受保护的AuthenticatedUser createUser(){
Map userAttrsMap=newhashmap();
userAttrsMap.put(“属性”,attrObject);
返回新的AuthenticatedUser(userId,displayName,this.getName(),userAttrsMap);
}
...
}
但是如果我们存储更大的数据(当userAttrsMap足够大时),我们将得到500错误

errorMsg:存储数据时遇到意外错误

错误如下所示:

完整源代码位于Github上:

MFP版本:

  • cordova插件mfp 8.0.2017102115
  • MFP开发日期:8.0.0.00-20171024-064640

发生此问题的原因是您在AuthenticatedUser对象中保存的数据的大小,从而导致Securitycheck的状态

MFP运行时将securitycheck的状态以及所有属性保存到属性存储中。这涉及序列化安全检查状态并将其持久化到数据库。对于大型对象(您拥有的自定义映射),此持久性操作将失败,并在事务回滚中结束。这是因为您试图持久化的数据太大,超出了分配的大小

SecurityCheck的设计考虑是将其用于安全检查(验证)和创建标识对象。在您的安全检查实现中,您具有以下功能:

//Here the large data is assigned to the variable.
attrObject = JSONObject.parse(largeJSONString);

//This data is set into the AuthenticatedUser object.
Map<String, Object> userAttrsMap = new HashMap<String, Object>();
userAttrsMap.put("attributes",attrObject);
return new AuthenticatedUser(userId, displayName, this.getName(), userAttrsMap);
//此处将大数据分配给变量。
attrObject=JSONObject.parse(largeJSONString);
//此数据被设置到AuthenticatedUser对象中。
Map userAttrsMap=newhashmap();
userAttrsMap.put(“属性”,attrObject);
返回新的AuthenticatedUser(userId,displayName,this.getName(),userAttrsMap);
在此场景中,此大数据将成为Securitycheck本身的一部分,并将被序列化并尝试持久化到属性存储中。当此数据不适合列时,将回滚事务,并将错误条件传播给最终用户。因此,您会看到错误消息-“存储数据时发生意外错误”。启用详细跟踪将在服务器跟踪日志中指出问题的实际原因

无论哪种方式,都不建议在生产系统中使用此方法,因为:

a) 从客户端到服务器的每一个请求都要经过安全自省,这将涉及服务器加载、检查和更新securitycheck的状态。在承受重负载(生产)的系统上,这可能并且将产生性能成本。这个过程包括序列化数据并在以后反序列化。在分布式拓扑(集群或场)中,请求可能会在任何节点中结束,这些节点将必须加载并稍后将安全检查的状态保存到存储。所有这些都会影响系统的性能

b) 在成功的身份验证结束时,AuthenticatedUser对象被传播到客户端应用程序,指示登录流的完成。即使将SecurityCheck状态成功存储在属性存储中(使用大数据),通过网络传输大有效负载以表明成功登录也会适得其反。对于终端用户来说,自从他们输入凭证后,似乎什么都没有发生,而表示成功的数据仍在下载中

c) 在重载情况下,服务器将受到上述a)和b)的影响


您应该考虑将被传播到身份验证用户对象内的客户端的数据进行裁剪。使AuthenticatedUser对象中的数据保持最少。相反,您应该将获取大数据的任务转移到资源适配器上,在成功登录后可以访问这些适配器。

您能说一下您试图存储的数据有多大吗?不知道数据的确切大小,但我们在这段代码中使用largeJSONString将得到500个错误