本文介绍了Spring Security 4 和 PrimeFaces 5 AJAX 请求处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

美好的一天.

我创建了一个 PrimeFaces 5 项目 (JSF 2.2),它使用 Spring Security 4.我试图使用启用单选的 p:dataTable 控件,它通过 ajax 调用更新 ap:pickList控制.

问题与Spring Security有关.如果我停用页面控件所在页面的安全性 (admin.faces),ajax 行为将正常工作.但是如果我激活安全性,我会得到 403 状态代码并且选择列表不会更新.我必须在这里指出,在激活安全性的情况下,如果我尝试进入管理页面,而没有先登录,我将被重定向到登录页面.

这是用于 Spring Security 的配置.为简单起见,删除了一些代码:

<beans:beans xmlns="http://www.springframework.org/schema/security"xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.1.xsdhttp://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security.xsd"><http pattern="/*.css" security="none"/><http pattern="/*.js" security="none"/><http use-expressions="true"><intercept-url pattern="/login.faces" access="permitAll"/><intercept-url pattern="/javax.faces.resource/**" access="permitAll"/><intercept-url pattern="/admin.faces" access="hasRole('Administrator')"/><表单登录登录页面=/login.faces"authentication-failure-url="/login.faces"/><退出/></http><authentication-manager alias="authManager"><authentication-provider ref="daoAuthenticationProvider"/></authentication-manager></beans:beans>

登录页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"xmlns:ui="http://java.sun.com/jsf/facelets"xmlns:f="http://java.sun.com/jsf/core"xmlns:h="http://java.sun.com/jsf/html"xmlns:p="http://primefaces.org/ui"><h:头><title>报告</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><meta name="_csrf" content="#{_csrf.token}"/><meta name="_csrf_header" content="#{_csrf.headerName}"/><link rel="stylesheet" type="text/css" href="stylesheet.css"/></h:head><身体><h:消息/><h:form id="登录表单"><input type="hidden" name="#{_csrf.parameterName}" value="#{_csrf.token}"/><p:panelGrid columns="2"><h:outputLabel value="用户:"/><h:inputText value="#{loginBean.user}" required="true"/><h:outputLabel value="密码:"/><h:inputSecret value="#{loginBean.password}" required="true"/><f:facet name="footer"><div style="text-align:right;"><h:commandButton type="submit" id="登录"action="#{loginBean.login}" value="登录"/>

</f:facet></p:panelGrid></h:form>

受保护页面(管理员):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"xmlns:h="http://java.sun.com/jsf/html"xmlns:f="http://java.sun.com/jsf/core"xmlns:p="http://primefaces.org/ui"><h:头><title>报告</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><meta name="_csrf" content="#{_csrf.token}"/><meta name="_csrf_header" content="#{_csrf.headerName}"/><link rel="stylesheet" type="text/css" href="stylesheet.css"/><h:outputScript library="primefaces" name="jquery/jquery.js"/><h:outputScript library="js" name="admin.js"/></h:head><身体><h1>报告</h1><br/><div><h:form id="表单"><input type="hidden" name="#{_csrf.parameterName}" value="#{_csrf.token}"/><p:messages id="messages" showDetail="false" showSummary="true"自动更新=真"可关闭=真"/><br/><div style="float: left; width: 25%; margin-right: 10px;"><p:dataTable value="#{reports.tables}" var="tbl"selection="#{reports.tablesel}" selectionMode="single"rowKey="#{tbl}" scrollable="true" scrollHeight="300" id="tables"><p:ajax event="rowSelect" update=":form:selColumns"/><p:列><f:facet name="header"><h:outputText value="表格"/></f:facet><h:outputText value="#{tbl}"/></p:列></p:dataTable>

<div style="float: left;"><div style="margin-bottom: 10px;"><div style="float: left; margin-right: 10px;"><p:selectOneMenu value="#{reports.format}"><f:selectItem itemValue="pdf" itemLabel="PDF"/><f:selectItem itemValue="xls" itemLabel="Excel 2003"/></p:selectOneMenu>

<div style="float: left; margin-right: 10px;"><p:commandButton action="#{reports.create}"值="查看报告"/>

<div style="clear: both;"></div>

<p:pickList value="#{reports.lstColumns}" var="c"itemLabel="#{c}" itemValue="#{c}" style="margin-bottom:10px;"id="selColumns"/><div style="margin-bottom: 10px;"><p:outputLabel value="Conditions" for="filter"样式=显示:块;"/><p:inputTextarea id="filter" value="#{reports.filter}"样式=宽度:97%;"/>

</h:form>

admin.faces 中使用的 javascript 文件:

$(document).ready(function() {var token = $("meta[name='_csrf']").attr("content");var header = $("meta[name='_csrf_header']").attr("content");$(document).ajaxSend(function(e, xhr, options) {xhr.setRequestHeader(header, token);})});

感谢您的关注.

解决方案

我也遇到了 AJAX 调用的 403 响应问题.问题是,没有提交 CSRF 令牌.

手动添加:

...<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/></h:form>

成功了.

Good Day.

I've created a PrimeFaces 5 project (JSF 2.2) which makes use of Spring Security 4. I'm attempting to make use of p:dataTable control with single selection enabled, which through an ajax call, updates a p:pickList control.

The problem is related with Spring Security. If I deactivate the security of the page where my page controls are located (admin.faces), the ajax behavior works fine. But if I activate security, I get 403 status codes and the pickList doesn't get updated. I must indicate here that with security activated, if I attempt going to admin page, without logging first, I'm redirected to the login page.

This is the configuration used for Spring Security. Several code was eliminated for sake of simplicity:

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
                    http://www.springframework.org/schema/security
                    http://www.springframework.org/schema/security/spring-security.xsd">

    <http pattern="/*.css" security="none" />
    <http pattern="/*.js" security="none" />

    <http use-expressions="true">
        <intercept-url pattern="/login.faces" access="permitAll" />
        <intercept-url pattern="/javax.faces.resource/**" access="permitAll"/>
        <intercept-url pattern="/admin.faces" access="hasRole('Administrator')" />

        <form-login
            login-page="/login.faces"
            authentication-failure-url="/login.faces" />
        <logout />
    </http>

    <authentication-manager alias="authManager">
        <authentication-provider ref="daoAuthenticationProvider"/>
    </authentication-manager>
</beans:beans>

The login page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui">

<h:head>
    <title>Reports</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="_csrf" content="#{_csrf.token}"/>
    <meta name="_csrf_header" content="#{_csrf.headerName}"/>
    <link rel="stylesheet" type="text/css" href="stylesheet.css" />
</h:head>
<body>
    <h:messages />
    <h:form id="loginForm">
        <input type="hidden" name="#{_csrf.parameterName}" value="#{_csrf.token}"/>

        <p:panelGrid columns="2">
            <h:outputLabel value="User:" />
            <h:inputText value="#{loginBean.user}" required="true"/>

            <h:outputLabel value="Password:" />
            <h:inputSecret value="#{loginBean.password}" required="true"/>

            <f:facet name="footer">
                <div style="text-align:right;">
                    <h:commandButton type="submit" id="login"
                        action="#{loginBean.login}" value="Login" />
                </div>
            </f:facet>
        </p:panelGrid>
    </h:form>
</body>
</html>

The protected page (admin):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<h:head>
    <title>Reports</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="_csrf" content="#{_csrf.token}"/>
    <meta name="_csrf_header" content="#{_csrf.headerName}"/>
    <link rel="stylesheet" type="text/css" href="stylesheet.css" />
    <h:outputScript library="primefaces" name="jquery/jquery.js"/>
    <h:outputScript library="js" name="admin.js"/>
</h:head>
<body>
    <h1>Reports</h1>
    <br />

    <div>
        <h:form id="form">
            <input type="hidden" name="#{_csrf.parameterName}" value="#{_csrf.token}"/>

            <p:messages id="messages" showDetail="false" showSummary="true"
                autoUpdate="true" closable="true" />
            <br />

            <div style="float: left; width: 25%; margin-right: 10px;">
                <p:dataTable value="#{reports.tables}" var="tbl"
                    selection="#{reports.tablesel}" selectionMode="single"
                    rowKey="#{tbl}" scrollable="true" scrollHeight="300" id="tables">
                    <p:ajax event="rowSelect" update=":form:selColumns" />

                    <p:column>
                        <f:facet name="header">
                            <h:outputText value="Tables" />
                        </f:facet>
                        <h:outputText value="#{tbl}" />
                    </p:column>
                </p:dataTable>
            </div>
            <div style="float: left;">
                <div style="margin-bottom: 10px;">
                    <div style="float: left; margin-right: 10px;">
                        <p:selectOneMenu value="#{reports.format}">
                            <f:selectItem itemValue="pdf" itemLabel="PDF" />
                            <f:selectItem itemValue="xls" itemLabel="Excel 2003" />
                        </p:selectOneMenu>
                    </div>
                    <div style="float: left; margin-right: 10px;">
                        <p:commandButton action="#{reports.create}"
                            value="View report" />
                    </div>
                    <div style="clear: both;"></div>
                </div>

                <p:pickList value="#{reports.lstColumns}" var="c"
                    itemLabel="#{c}" itemValue="#{c}" style="margin-bottom:10px;"
                    id="selColumns" />

                <div style="margin-bottom: 10px;">
                    <p:outputLabel value="Conditions" for="filter"
                        style="display:block;" />
                    <p:inputTextarea id="filter" value="#{reports.filter}"
                        style="width:97%;" />
                </div>

            </div>
        </h:form>
    </div>
</body>
</html>

A javascript file used in admin.faces:

$(document).ready(function() {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    $(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader(header, token);
    })
});

Thanks for your attention.

解决方案

I had the problem with 403 Responses for AJAX calls as well.The Problem was, that no CSRF Token was submitted.

By manually adding:

<h:form>
    ...
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</h:form>

it worked.

这篇关于Spring Security 4 和 PrimeFaces 5 AJAX 请求处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 19:14