Hybris表单组件验证

时间:2018-09-26 06:59:02

标签: java hybris

我编写了自定义组件,它是简单的形式。提交表单后,我要验证表单,如果出现错误,我想显示它们。我试图在我的类MyFormComponentController extends AbstractAcceleratorCMSComponentController<MyFormComponentModel>中创建带有POST请求映射的方法,但出现一条错误消息,指出不允许使用该方法。所以我写了一个控制器,并向表单组件添加了动作

@Controller
@RequestMapping(value = "/action")
public class MyFormPageController extends AbstractPageController {

    @RequestMapping(method = RequestMethod.POST)
    public String doMyPageController(@Valid final MyForm myForm, final BindingResult bindingResult, final Model model)
            return ???; //..in case of error?

但是当我的表单中有错误并且我不想返回时返回到视图时,仅显示组件。我试图将在组件控制器中从getView()方法获得的值传递给该函数,但这没有帮助。

编辑:我还试图通过ajax调用来提交表单,例如:

$(document).on("submit",'#myForm', function(e){
            e.preventDefault();
            var postData = $("#myForm").serialize();
            var url= $(".js-my-action").data("url");
            $.ajax({
                url: url,
                data: JSON.stringify(postData),
                type: "POST",
                success: function (response){
                }
            });
        })

我想调用的方法是

@RequestMapping(value = "/action", method = RequestMethod.POST)
    public String doMyPageController(@RequestBody @Valid final MyForm catalogOrderForm, final Model model) throws IOException, JaloBusinessException, CMSItemNotFoundException {

在这里,我尝试使用表单名称将@RequestBody更改为@ModelAttribute,但我只收到Acces denied (CSRFToken)错误:

ERROR [hybrisHTTP24] [SikoAcceleratorAccessDeniedHandler] Access denied happend - org.springframework.security.web.csrf.InvalidCsrfTokenException: Invalid CSRF Token '66d045fd-c9ae-4210-ae97-f2a0e739bcbf"' was found on the request parameter 'CSRFToken' or header 'CSRFToken'.

我在ajax调用中传递的数据:

"firstName=Test&lastName=Test&street=Test&city=Test&postalCode=38801&email=test%40test.com&_inspiration=on&_kitchen=on&_door=on&_gdpr=on&CSRFToken=66d045fd-c9ae-4210-ae97-f2a0e739bcbf"

然后我尝试在ajax调用中传递数据,例如:

data: {myForm: postData}

但是它也不起作用。

4 个答案:

答案 0 :(得分:0)

您可以使用ResponseEntity作为返​​回类型。

EntityBareJid mucJid = JidCreate.entityBareFrom("groupname@conference.servicename");

MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(conn);

MultiUserChat muc = manager.getMultiUserChat(mucJid);

Resourcepart nickname = Resourcepart.from("admin");

List<String> owners = new ArrayList<>();
owners.add("user1@servicename");
owners.add("user2@servicename");

muc.create(nickname);
Form form = muc.getConfigurationForm().createAnswerForm();
form.setAnswer("muc#roomconfig_roomowners", owners);
muc.sendConfigurationForm(form);

您需要在jsp文件中处理此响应。 Accelerator有一些用于处理这些响应的标签,您可以检查模板店面。

答案 1 :(得分:0)

由于您使用的是Spring,答案为mind bendingly easy

在您的控制器类上 @Valid批注

这将导致从控制器返回400错误以及JSON有效负载,从而阐明遇到的每个错误的确切错误原因。

请参阅Spring 3类型转换和验证

答案 2 :(得分:0)

不同页面上的组件- 由于您已经创建了呈现表单的组件,因此希望您可以在多个页面上使用该组件。在这种情况下,您不能返回任何硬代码视图,因为可以从任何页面(视图)提交表单。我建议通过ajax调用处理表单提交。

单个页面上的组件-如果您知道此组件将在单个页面上使用。然后,您可以简单地使用常规页面提交并从控制器返回该页面视图。在这里,您不需要使用AJAX。


建议:

您可以创建 JspIncludeComponent 实例并指向您的JSP / VIEW,而不是仅为表单创建自定义组件。

喜欢

$contentCatalog=yourContentCatalog
$contentCV=catalogVersion(catalog(id[default=$contentCatalog]),version[default='Staged'])

INSERT_UPDATE JspIncludeComponent ; $contentCV[unique=true] ; uid[unique=true]    ; name                  ; page                                          
                                  ;                         ; formComponent       ; Form Component        ; /WEB-INF/views/desktop/pages/form/newsForm.jsp 

编辑:

拒绝访问(CSRFToken)错误-Hybris Commerce提供了默认情况下启用的CSRF保护机制。 CSRFHandlerInterceptor验证CSRF令牌的每个POST请求。要绕过任何请求的CSRF检查,您可以将网址格式添加到csrfAllowedUrlPatterns列表中。

要解决您的问题,只需使用spring表单,即可在隐藏字段中呈现CSRFToken。现在,您可以使用form.serialize()提交整个表单。

JSP:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

    <form:form id="myForm" action="${myFormActionURL}" method="POST" modelAttribute="myForm">
        <input type="text" placeholder="<spring:theme code="myform.firstName"/>" name="fname" required>
         ...
    </form:form>

AJAX:

var form = $("#myForm");
    $.ajax({
        url: url,
        data: form.serialize(),
        type: 'POST',
        success: function (data) {

        },
        error: function (data) {

        }
    });

控制器:

@SuppressWarnings("boxing")
@ResponseBody
@RequestMapping(value = "/myForm", method = RequestMethod.POST)
public String saveMyForm(@Valid @ModelAttribute("myForm") final MyForm myForm, final Model model)
{
        return "succcess";
}

答案 3 :(得分:0)

在CMS组件中使用表单是一个棘手的问题。解决方案可能取决于您的用例。到目前为止,这里有一些解决方案:

仅在特定的URL /页面上使用组件 考虑购物车页面。有很多形式。它们仅应在购物车页面(/ cart)上使用。您还可以定义一个内容页面以在失败/成功的情况下进行查看。搜索页面就是一个例子。使用搜索组件时,输入搜索词时,始终将您重定向到搜索页面/搜索空白页面。

使用引荐信息 登录组件使用更智能的方法。当您从特定页面(例如产品页面)登录时,登录控制器会检查引荐来源网址并重定向到您之前访问过的页面。

URL形式的参数 一些解决方案在表单中添加了一个附加的字符串参数来存储当前URL。我还看到了使用SessionService在会话中存储参数的解决方案。然而,该解决方案的缺点在于,在一个会话中只能使用一种形式。

配置每个CMS组件的使用位置以及重定向到成功/失败的位置 还可以定义特定的内容页面/ URL,以在成功/失败之后显示。在这种情况下,您可能有该组件的多个实例,一旦成功/失败,它们都将重定向到特定页面。

使用AJAX 另一种解决方案是使用AJAX提交表单并使用JavaScript处理失败/成功操作。

可能还有其他更有效的实现。请和我分享您的想法。