掲示板

Liferay + Alfresco CSRF

7年前 に Andrey Sytchev によって更新されました。

Liferay + Alfresco CSRF

New Member 投稿: 1 参加年月日: 16/07/08 最新の投稿
Всем доброго дня.
Проблема следующего характера:
По задаче руководства поднимаем корпоративный портал на базе LifeRay в связке с документоборотом Alfresco.
Поднимаем на Ubuntu Server 14.2
Alfresco Version 4.2.f
LifeRay Version 6.2.f
Используем базу MySQL
Всё подняли. Портлет прикрутили. Всё находится на одном физическом серваке.
Итак собственно сама проблема:
При входе напрямую в Alfresco по порту, заданному в конфиге, можно производить любые манипуляции такие как: создать/удалить файл/папку, загрузить файл, создать сайт.
Но при входе в Alfresco через портлет в LifeRay ничего не выходит. В логах LifeRay постоянно одна и та же ошибка:
ERROR [alfresco.web.site] [http-bio-80-exec-20] javax.servlet.ServletException: Possible CSRF attack noted when comparing token in session and request header. Request: POST /share/proxy/alfresco/api/type/cm%3afolder/formprocessor

Ковыряли конфиги Alfresco: share-config-custom.xml и share-security-config.xml
share-config-custom.xml
<alfresco-config>

   <!-- Global config section -->
   <config replace="true">
      <flags>
         <!--
            Developer debugging setting to turn on DEBUG mode for client scripts in the browser
         -->
         <client-debug>false</client-debug>

         <!--
            LOGGING can always be toggled at runtime when in DEBUG mode (Ctrl, Ctrl, Shift, Shift).
            This flag automatically activates logging on page load.
         -->
         <client-debug-autologging>false</client-debug-autologging>
      </flags>
   </config>
   
   <config evaluator="string-compare" condition="WebFramework">
      <web-framework>
         <!-- SpringSurf Autowire Runtime Settings -->
         <!-- 
              Developers can set mode to 'development' to disable; SpringSurf caches,
              FreeMarker template caching and Rhino JavaScript compilation.
         -->
         <autowire>
            <!-- Pick the mode: "production" or "development" -->
            <mode>production</mode>
         </autowire>

         <!-- Allows extension modules with <auto-deploy> set to true to be automatically deployed -->
         <module-deployment>
            <mode>manual</mode>
            <enable-auto-deploy-modules>true</enable-auto-deploy-modules>
         </module-deployment>
      </web-framework>
   </config>

   <!-- Disable the CSRF Token Filter -->
   <!--
   <config evaluator="string-compare" condition="CSRFPolicy" replace="true">
      <filter/>
   </config>
   -->
   <config evaluator="string-compare" condition="CSRFPolicy" replace="true">

      <!--
         Properties that may be used inside the rest of the CSRFPolicy config to avoid repetition but
         also making it possible to provide different values in different environments.
         I.e. Different "Referer" & "Origin" properties for test & production etc.
         Reference a property using "{propoertyName}".
      -->
      <properties>

         <!-- There is normally no need to override this property -->
         <token>Alfresco-CSRFToken</token>

         <!--
            Override and set this property with a regexp that if you have placed Share behind a proxy that
            does not rewrite the Referer header.
         -->
         <referer>http://192.168.2.251/.*</referer>

         <!--
            Override and set this property with a regexp that if you have placed Share behind a proxy that
            does not rewrite the Origin header.
         -->
         <origin>http://192.168.2.251</origin>
      </properties>

      <!--
        Will be used and exposed to the client side code in Alfresco.contants.CSRF_POLICY.
        Use the Alfresco.util.CSRFPolicy.getHeader() or Alfresco.util.CSRFPolicy.getParameter() with Alfresco.util.CSRFPolicy.getToken()
        to set the token in custom 3rd party code.
      -->
      <client>
         <cookie>{token}</cookie>
         <header>{token}</header>
         <parameter>{token}</parameter>
      </client>

      <!-- The first rule with a matching request will get its action invoked, the remaining rules will be ignored. -->
      <filter>
			<rule>
				<request>
					<method>POST</method>
						<path>/page/trusted/call/1|/page/trusted/call/2</path>
				</request>
					<action name="assertReferer">
						<param name="always">false
						<param name="referer">http://192.168.2.251/.*
					</action>
					<action name="assertOrigin">
						<param name="always">false
						<param name="origin">http://192.168.2.251
					</action>
			</rule>
         <!--
            Certain webscripts shall not be allowed to be accessed directly form the browser.
            Make sure to throw an error if they are used.
         -->
         <rule>
            <request>
               <path>/proxy/alfresco/remoteadm/.*</path>
            </request>
            <action name="throwError">
               <param name="message">It is not allowed to access this url from your browser
            </action>
         </rule>

         <!--
            Certain Repo webscripts should be allowed to pass without a token since they have no Share knowledge.
            TODO: Refactor the publishing code so that form that is posted to this URL is a Share webscript with the right tokens.
         -->
         <rule>
            <request>
               <method>POST</method>
               <path>/proxy/alfresco/api/publishing/channels/.+</path>
            </request>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>

         <!--
            Certain Surf POST requests from the WebScript console must be allowed to pass without a token since
            the Surf WebScript console code can't be dependent on a Share specific filter.
         -->
         <rule>
            <request>
               <method>POST</method>
               <path>/page/caches/dependency/clear|/page/index|/page/surfBugStatus|/page/modules/deploy|/page/modules/module|/page/api/javascript/debugger|/page/console</path>
            </request>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>

         <!-- Certain Share POST requests does NOT require a token -->
         <rule>
            <request>
               <method>POST</method>
               <path>/page/dologin(\?.+)?|/page/site/[^/]+/start-workflow|/page/start-workflow|/page/context/[^/]+/start-workflow</path>
            </request>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>

         <!-- Assert logout is done from a valid domain, if so clear the token when logging out -->
         <rule>
            <request>
               <method>GET</method>
               <path>/page/dologout(\?.+)?</path>
            </request>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
            <action name="clearToken">
               <param name="session">{token}
               <param name="cookie">{token}
            </action>
         </rule>

         <!-- Make sure the first token is generated -->
         <rule>
            <request>
               <session>
                  <attribute name="_alf_USER_ID">.+</attribute>
                  <attribute name="{token}" />
                  <!-- empty attribute element indicates null, meaning the token has not yet been set -->
               </session>
            </request>
            <action name="generateToken">
               <param name="session">{token}
               <param name="cookie">{token}
            </action>
         </rule>

         <!-- Refresh token on new "page" visit when a user is logged in -->
         <rule>
            <request>
               <method>GET</method>
               <path>/page/.*</path>
               <session>
                  <attribute name="_alf_USER_ID">.+</attribute>
                  <attribute name="{token}">.+</attribute>
               </session>
            </request>
            <action name="generateToken">
               <param name="session">{token}
               <param name="cookie">{token}
            </action>
         </rule>

         <!--
            Verify multipart requests from logged in users contain the token as a parameter
            and also correct referer & origin header if available
         -->
         <rule>
            <request>
               <method>POST</method>
               <header name="Content-Type">multipart/.+</header>
               <session>
                  <attribute name="_alf_USER_ID">.+</attribute>
               </session>
            </request>
            <action name="assertToken">
               <param name="session">{token}
               <param name="parameter">{token}
            </action>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>

         <!--
            Verify that all remaining state changing requests from logged in users' requests contains a token in the
            header and correct referer & origin headers if available. We "catch" all content types since just setting it to
            "application/json.*" since a webscript that doesn't require a json request body otherwise would be
            successfully executed using i.e."text/plain".
         -->
         <rule>
            <request>
               <method>POST|PUT|DELETE</method>
               <session>
                  <attribute name="_alf_USER_ID">.+</attribute>
               </session>
            </request>
            <action name="assertToken">
               <param name="session">{token}
               <param name="header">{token}
            </action>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>
      </filter>

   </config>	
   <!--
      To run the CSRF Token Filter behind 1 or more proxies that do not rewrite the Origin or Referere headers:

      1. Copy the "CSRFPolicy" default config in share-security-config.xml and paste it into this file.
      2. Replace the old config by setting the <config> element's "replace" attribute to "true" like below:
         <config evaluator="string-compare" condition="CSRFPolicy" replace="true">
      3. To every <action name="assertReferer"> element add the following child element
         <param name="referer">http://www.proxy1.com/.*|http://www.proxy2.com/.*</param>
      4. To every <action name="assertOrigin"> element add the following child element
         <param name="origin">http://www.proxy1.com|http://www.proxy2.com</param>
   -->

   <!--
      Remove the default wildcard setting and use instead a strict whitelist of the only domains that shall be allowed
      to be used inside iframes (i.e. in the WebView dashlet on the dashboards)
   -->
   <!--
   <config evaluator="string-compare" condition="IFramePolicy" replace="true">
      <cross-domain>
         <url>http://www.trusted-domain-1.com/</url>
         <url>http://www.trusted-domain-2.com/</url>
      </cross-domain>
   </config>
   -->

   <!-- Turn off header that stops Share from being displayed in iframes on pages from other domains -->
   <!--
   <config evaluator="string-compare" condition="SecurityHeadersPolicy">
      <headers>
         <header>
            <name>X-Frame-Options</name>
            <enabled>false</enabled>
         </header>
      </headers>
   </config>
   -->

   <!-- Prevent browser communication over HTTP (for HTTPS servers) -->
   <!--
   <config evaluator="string-compare" condition="SecurityHeadersPolicy">
      <headers>
         <header>
            <name>Strict-Transport-Security</name>
            <value>max-age=31536000</value>
         </header>
      </headers>
   </config>
   -->

   <config evaluator="string-compare" condition="Replication">
      <share-urls>
         <!--
            To discover a Repository Id, browse to the remote server's CMIS landing page at:
              http://{server}:{port}/alfresco/service/cmis/index.html
            The Repository Id field is found under the "CMIS Repository Information" expandable panel.

            Example config entry:
              <share-url repositoryId="622f9533-2a1e-48fe-af4e-ee9e41667ea4">http://new-york-office:8080/share/</share-url>
         -->
      </share-urls>
   </config>

   <!-- Document Library config section -->
   <config evaluator="string-compare" condition="DocumentLibrary" replace="true">

      <tree>
         <!--
            Whether the folder Tree component should enumerate child folders or not.
            This is a relatively expensive operation, so should be set to "false" for Repositories with broad folder structures.
         -->
         <evaluate-child-folders>false</evaluate-child-folders>
         
         <!--
            Optionally limit the number of folders shown in treeview throughout Share.
         -->
         <maximum-folder-count>1000</maximum-folder-count>
         
         <!--  
            Default timeout in milliseconds for folder Tree component to recieve response from Repository
         -->
         <timeout>7000</timeout>
      </tree>

      <!--
         Used by the "Manage Aspects" action

         For custom aspects, remember to also add the relevant i18n string(s)
            cm_myaspect=My Aspect
      -->
      <aspects>
         <!-- Aspects that a user can see -->
         <visible>
            <aspect name="cm:generalclassifiable" />
            <aspect name="cm:complianceable" />
            <aspect name="cm:dublincore" />
            <aspect name="cm:effectivity" />
            <aspect name="cm:summarizable" />
            <aspect name="cm:versionable" />
            <aspect name="cm:templatable" />
            <aspect name="cm:emailed" />
            <aspect name="emailserver:aliasable" />
            <aspect name="cm:taggable" />
            <aspect name="app:inlineeditable" />
            <aspect name="gd:googleEditable" />
            <aspect name="cm:geographic" />
            <aspect name="exif:exif" />
            <aspect name="audio:audio" />
            <aspect name="cm:indexControl" />
            <aspect name="dp:restrictable" />
         </visible>

         <!-- Aspects that a user can add. Same as "visible" if left empty -->
         <addable>
         </addable>

         <!-- Aspects that a user can remove. Same as "visible" if left empty -->
         <removeable>
         </removeable>
      </aspects>

      <!--
         Used by the "Change Type" action

         Define valid subtypes using the following example:
            <type name="cm:content">
               <subtype name="cm:mysubtype" />
            </type>

         Remember to also add the relevant i18n string(s):
            cm_mysubtype=My SubType
      -->
      <types>
         <type name="cm:content">
         </type>

         <type name="cm:folder">
         </type>
 
         <type name="trx:transferTarget">
            <subtype name="trx:fileTransferTarget" />
         </type>
      </types>

      <!--
         If set, will present a WebDAV link for the current item on the Document and Folder details pages.
         Also used to generate the "View in Alfresco Explorer" action for folders.
      -->
      <repository-url>http://localhost:8080/alfresco</repository-url>

      <!--
         Google Docs™ integration
      -->
      <google-docs>
         <!--
            Enable/disable the Google Docs UI integration (Extra types on Create Content menu, Google Docs actions).
         -->
         <enabled>false</enabled>

         <!--
            The mimetypes of documents Google Docs allows you to create via the Share interface.
            The I18N label is created from the "type" attribute, e.g. google-docs.doc=Google Docs&trade; Document
         -->
         <creatable-types>
            <creatable type="doc">application/msword</creatable>
            <creatable type="xls">application/vnd.ms-excel</creatable>
            <creatable type="ppt">application/vnd.ms-powerpoint</creatable>
         </creatable-types>
      </google-docs>

      <!--
         File upload configuration
      -->
      <file-upload>
         <!--
            Adobe Flash™
            In certain environments, an HTTP request originating from Flash cannot be authenticated using an existing session.
            See: http://bugs.adobe.com/jira/browse/FP-4830
            For these cases, it is useful to disable the Flash-based uploader for Share Document Libraries.
         -->
         <adobe-flash-enabled>true</adobe-flash-enabled>
      </file-upload>
   </config>


   <!-- Custom DocLibActions config section -->
   <config evaluator="string-compare" condition="DocLibActions">
      <actiongroups>
         <actiongroup id="document-browse">

            <!-- Simple Repo Actions -->
            <!--
            <action index="340" id="document-extract-metadata" />
            <action index="350" id="document-increment-counter" />
            -->

            <!-- Dialog Repo Actions -->
            <!--
            <action index="360" id="document-transform" />
            <action index="370" id="document-transform-image" />
            <action index="380" id="document-execute-script" />
            -->

         </actiongroup>
      </actiongroups>
   </config>

   <!-- Global folder picker config section -->
   <config evaluator="string-compare" condition="GlobalFolder">
      <sitetree>
         <container type="cm:folder">
            <!-- Use a specific label for this container type in the tree -->
            <rootlabel>location.path.documents</rootlabel>
            <!-- Use a specific uri to retreive the child nodes for this container type in the tree -->
            <uri>slingshot/doclib/treenode/site/{site}/{container}{path}?children={evaluateChildFoldersSite}&amp;max={maximumFolderCountSite}</uri>
         </container>
      </sitetree>
   </config>

   <!-- Repository Library config section -->
   <config evaluator="string-compare" condition="RepositoryLibrary" replace="true">
      <!--
         Root nodeRef or xpath expression for top-level folder.
         e.g. alfresco://user/home, /app:company_home/st:sites/cm:site1
         If using an xpath expression, ensure it is properly ISO9075 encoded here.
      -->
      <root-node>alfresco://company/home</root-node>

      <tree>
         <!--
            Whether the folder Tree component should enumerate child folders or not.
            This is a relatively expensive operation, so should be set to "false" for Repositories with broad folder structures.
         -->
         <evaluate-child-folders>false</evaluate-child-folders>
         
         <!--
            Optionally limit the number of folders shown in treeview throughout Share.
         -->
         <maximum-folder-count>500</maximum-folder-count>
      </tree>

      <!--
         Whether the link to the Repository Library appears in the header component or not.
      -->
      <visible>true</visible>
   </config>
   
   <!-- Kerberos settings -->
   <!-- To enable kerberos rename this condition to "Kerberos" -->
   <config evaluator="string-compare" condition="KerberosDisabled" replace="true">
      <kerberos>
         <!--
            Password for HTTP service account.
            The account name *must* be built from the HTTP server name, in the format :
               HTTP/<server_name>@<realm>
            (NB this is because the web browser requests an ST for the
            HTTP/<server_name> principal in the current realm, so if we're to decode
            that ST, it has to match.)
         -->
         <password>secret</password>
         <!--
            Kerberos realm and KDC address.
         -->
         <realm>ALFRESCO.ORG</realm>
         <!--
            Service Principal Name to use on the repository tier.
            This must be like: HTTP/host.name@REALM
         -->
         <endpoint-spn>HTTP/repository.server.com@ALFRESCO.ORG</endpoint-spn>
         <!--
            JAAS login configuration entry name.
         -->
         <config-entry>ShareHTTP</config-entry>
      </kerberos>
   </config>

   <config evaluator="string-compare" condition="Remote">
      <remote>
         <endpoint>
            <id>alfresco-noauth</id>
            <name>Alfresco - unauthenticated access</name>
            <description>Access to Alfresco Repository WebScripts that do not require authentication</description>
            <connector-id>alfresco</connector-id>
            <endpoint-url>http://localhost:8080/alfresco/s</endpoint-url>
            <identity>none</identity>
         </endpoint>

         <endpoint>
            <id>alfresco</id>
            <name>Alfresco - user access</name>
            <description>Access to Alfresco Repository WebScripts that require user authentication</description>
            <connector-id>alfresco</connector-id>
            <endpoint-url>http://localhost:8080/alfresco/s</endpoint-url>
            <identity>user</identity>
         </endpoint>

         <endpoint>
            <id>alfresco-feed</id>
            <name>Alfresco Feed</name>
            <description>Alfresco Feed - supports basic HTTP authentication via the EndPointProxyServlet</description>
            <connector-id>http</connector-id>
            <endpoint-url>http://localhost:8080/alfresco/s</endpoint-url>
            <basic-auth>true</basic-auth>
            <identity>user</identity>
         </endpoint>
         
         <endpoint>
            <id>activiti-admin</id>
            <name>Activiti Admin UI - user access</name>
            <description>Access to Activiti Admin UI, that requires user authentication</description>
            <connector-id>activiti-admin-connector</connector-id>
            <endpoint-url>http://localhost:8080/alfresco/activiti-admin</endpoint-url>
            <identity>user</identity>
         </endpoint>
      </remote>
   </config>

   <!-- 
        Overriding endpoints to reference an Alfresco server with external SSO enabled
        NOTE: If utilising a load balancer between web-tier and repository cluster, the "sticky
              sessions" feature of your load balancer must be used.
        NOTE: If alfresco server location is not localhost:8080 then also combine changes from the
              "example port config" section below.
        *Optional* keystore contains SSL client certificate + trusted CAs.
        Used to authenticate share to an external SSO system such as CAS
        Remove the keystore section if not required i.e. for NTLM.
        
        NOTE: For Kerberos SSO rename the "KerberosDisabled" condition above to "Kerberos"
        
        NOTE: For external SSO, switch the endpoint connector to "AlfrescoHeader" and set
              the userHeader to the name of the HTTP header that the external SSO
              uses to provide the authenticated user name.
   -->
   <!--
   <config evaluator="string-compare" condition="Remote">
      <remote>
         <keystore>
             <path>alfresco/web-extension/alfresco-system.p12</path>
             <type>pkcs12</type>
             <password>alfresco-system</password>
         </keystore>
         
         <connector>
            <id>alfrescoCookie</id>
            <name>Alfresco Connector</name>
            <description>Connects to an Alfresco instance using cookie-based authentication</description>
            <class>org.alfresco.web.site.servlet.SlingshotAlfrescoConnector</class>
         </connector>
         
         <connector>
            <id>alfrescoHeader</id>
            <name>Alfresco Connector</name>
            <description>Connects to an Alfresco instance using header and cookie-based authentication</description>
            <class>org.alfresco.web.site.servlet.SlingshotAlfrescoConnector</class>
            <userHeader>SsoUserHeader</userHeader>
         </connector>

         <endpoint>
            <id>alfresco</id>
            <name>Alfresco - user access</name>
            <description>Access to Alfresco Repository WebScripts that require user authentication</description>
            <connector-id>alfrescoCookie</connector-id>
            <endpoint-url>http://localhost:8080/alfresco/wcs</endpoint-url>
            <identity>user</identity>
            <external-auth>true</external-auth>
         </endpoint>
      </remote>
   </config>
   -->
   
</alfresco-config>

share-security-config.xml
<alfresco-config>

   <!--
      This setting controls which domains' pages that shall be allowed to be included inside Share using an <iframe>.
      All components in Share that creates an <iframe> (targeted at a user provided url) MUST assert the url is
      provided in the white list below or that it.

      Will be used and exposed to the client side code in Alfresco.contants.IFRAME_POLICY.
      Use the Alfresco.util.IFramePolicy.isUrlAllowed() to check if a url is allowed.

      Note!
      These settings are used to mitigate phishing attacks (i.e. displaying a login form).
      These settings are NOT used to mitigate clickjacking attacks and do NOT control if or when Share is allowed
      to be included into pages (using an <iframe>) from other domains, that is instead controlled by the
      "X-Frame-Options" header inside the "SecurityHeadersPolicy" config.
   -->
   <config evaluator="string-compare" condition="IFramePolicy">

      <!-- Local share pages/resources are governed by the same-domain element which can be set to "allow" or "deny" -->
      <same-domain>allow</same-domain>

      <!--
         Add a list of <url> elements inside this element to form a whitelist of allowed domains.
         The check will assert that the url used for the <iframe> starts with the value of one of the <url> elements.
      -->
      <cross-domain>
         <!--
            Allow all domains by default, it is highly recommended to override this setting and instead keep a
            whitelist of the domains that you trust to be included on Share pages.
         -->
         <url>*</url>
      </cross-domain>
   </config>

   <!--
      CSRF filter config to mitigate CSRF/Seasurfing/XSRF attacks

      To disable the CSRF filter override the <filter> to not contain any values, see share-config-custom.xml for
      an example.

      If you have a custom resource(s) that a client POST to that can't accept a token, for whatever reason, then make
      sure to copy the entire CSRFPolicy config and place it in your share-config-custom.xml file
      with the replace="true" attribute and make sure to add a new <rule> in the top of the <filter> element,
      which has a <request> element matching your requests, and uses only the "assertReferer" & "assertOrigin" actions.

      I.e.
      <rule>
         <request>
            <method>POST</method>
            <path>/proxy/alfresco/custom/repoWebscript/withoutParams|/service/custom/shareResource/thatMayHaveParams(\?.+)?</path>
         </request>
         <action name="assertReferer">
            <param name="referer">{referer}</param>
         </action>
         <action name="assertOrigin">
            <param name="origin">{origin}</param>
         </action>
      </rule>
   -->
   <config evaluator="string-compare" condition="CSRFPolicy">

      <!--
         Properties that may be used inside the rest of the CSRFPolicy config to avoid repetition but
         also making it possible to provide different values in different environments.
         I.e. Different "Referer" & "Origin" properties for test & production etc.
         Reference a property using "{propoertyName}".
      -->
      <properties>

         <!-- There is normally no need to override this property -->
         <token>Alfresco-CSRFToken</token>

         <!--
            Override and set this property with a regexp that if you have placed Share behind a proxy that
            does not rewrite the Referer header.
         -->
         <referer></referer>

         <!--
            Override and set this property with a regexp that if you have placed Share behind a proxy that
            does not rewrite the Origin header.
         -->
         <origin></origin>
      </properties>

      <!--
        Will be used and exposed to the client side code in Alfresco.contants.CSRF_POLICY.
        Use the Alfresco.util.CSRFPolicy.getHeader() or Alfresco.util.CSRFPolicy.getParameter() with Alfresco.util.CSRFPolicy.getToken()
        to set the token in custom 3rd party code.
      -->
      <client>
         <cookie>{token}</cookie>
         <header>{token}</header>
         <parameter>{token}</parameter>
      </client>

      <!-- The first rule with a matching request will get its action invoked, the remaining rules will be ignored. -->
      <filter>

         <!--
            Certain webscripts shall not be allowed to be accessed directly form the browser.
            Make sure to throw an error if they are used.
         -->
         <rule>
            <request>
               <path>/proxy/alfresco/remoteadm/.*</path>
            </request>
            <action name="throwError">
               <param name="message">It is not allowed to access this url from your browser
            </action>
         </rule>

         <!--
            Certain Repo webscripts should be allowed to pass without a token since they have no Share knowledge.
            TODO: Refactor the publishing code so that form that is posted to this URL is a Share webscript with the right tokens.
         -->
         <rule>
            <request>
               <method>POST</method>
               <path>/proxy/alfresco/api/publishing/channels/.+</path>
            </request>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>

         <!--
            Certain Surf POST requests from the WebScript console must be allowed to pass without a token since
            the Surf WebScript console code can't be dependent on a Share specific filter.
         -->
         <rule>
            <request>
               <method>POST</method>
               <path>/page/caches/dependency/clear|/page/index|/page/surfBugStatus|/page/modules/deploy|/page/modules/module|/page/api/javascript/debugger|/page/console</path>
            </request>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>

         <!-- Certain Share POST requests does NOT require a token -->
         <rule>
            <request>
               <method>POST</method>
               <path>/page/dologin(\?.+)?|/page/site/[^/]+/start-workflow|/page/start-workflow|/page/context/[^/]+/start-workflow</path>
            </request>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>

         <!-- Assert logout is done from a valid domain, if so clear the token when logging out -->
         <rule>
            <request>
               <method>GET</method>
               <path>/page/dologout(\?.+)?</path>
            </request>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
            <action name="clearToken">
               <param name="session">{token}
               <param name="cookie">{token}
            </action>
         </rule>

         <!-- Make sure the first token is generated -->
         <rule>
            <request>
               <session>
                  <attribute name="_alf_USER_ID">.+</attribute>
                  <attribute name="{token}" />
                  <!-- empty attribute element indicates null, meaning the token has not yet been set -->
               </session>
            </request>
            <action name="generateToken">
               <param name="session">{token}
               <param name="cookie">{token}
            </action>
         </rule>

         <!-- Refresh token on new "page" visit when a user is logged in -->
         <rule>
            <request>
               <method>GET</method>
               <path>/page/.*</path>
               <session>
                  <attribute name="_alf_USER_ID">.+</attribute>
                  <attribute name="{token}">.+</attribute>
               </session>
            </request>
            <action name="generateToken">
               <param name="session">{token}
               <param name="cookie">{token}
            </action>
         </rule>

         <!--
            Verify multipart requests from logged in users contain the token as a parameter
            and also correct referer & origin header if available
         -->
         <rule>
            <request>
               <method>POST</method>
               <header name="Content-Type">multipart/.+</header>
               <session>
                  <attribute name="_alf_USER_ID">.+</attribute>
               </session>
            </request>
            <action name="assertToken">
               <param name="session">{token}
               <param name="parameter">{token}
            </action>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>

         <!--
            Verify that all remaining state changing requests from logged in users' requests contains a token in the
            header and correct referer & origin headers if available. We "catch" all content types since just setting it to
            "application/json.*" since a webscript that doesn't require a json request body otherwise would be
            successfully executed using i.e."text/plain".
         -->
         <rule>
            <request>
               <method>POST|PUT|DELETE</method>
               <session>
                  <attribute name="_alf_USER_ID">.+</attribute>
               </session>
            </request>
            <action name="assertToken">
               <param name="session">{token}
               <param name="header">{token}
            </action>
            <action name="assertReferer">
               <param name="referer">{referer}
            </action>
            <action name="assertOrigin">
               <param name="origin">{origin}
            </action>
         </rule>
      </filter>

   </config>

   <!--
      A set of HTTP response headers that instructs the browser to behave in certain ways to improve security

      The header name is (of course) unique meaning that a <header> element can be override to provide a different
      <value> or be disabled (by creating a <enabled>false</enabled> element as a child to the <header> element).
      See the share-config-custom.xml.sample for examples.
   -->
   <config evaluator="string-compare" condition="SecurityHeadersPolicy">
      <headers>
         <!--
            Setting to allow the embedding of Share within an IFRAME by other domains.
            DENY        = Don't allow Share to be included in any iframe
            SAMEORIGIN  = Only allow Share to be included in pages from the same domain
         -->
         <header>
            <name>X-Frame-Options</name>
            <value>SAMEORIGIN</value>
         </header>

         <!--
            Stop IE from guessing (and then "correcting") the Content-Type
         -->
         <header>
            <name>X-Content-Type-Options</name>
            <value>nosniff</value>
         </header>

         <!--
            Stop IE from trying to be "smart" and mitigating XSS attacks but instead introducing new ones:
            http://www.h-online.com/security/news/item/Security-feature-of-Internet-Explorer-8-unsafe-868837.html
            0              = Stop IE's XSS protection
            1; mode=block  = Run IE's XSS protection, but if XSS is found then block the page instead of trying to
                             "fix" the problem and then introducing new security flaws
         -->
         <header>
            <name>X-XSS-Protection</name>
            <value>1; mode=block</value>
         </header>
      </headers>
   </config>


</alfresco-config>



Если знаете в чём проблема, прошу вашей помощи. Заранее спасибо.
thumbnail
7年前 に Pavel Savinov によって更新されました。

RE: Liferay + Alfresco CSRF

Junior Member 投稿: 54 参加年月日: 15/05/29 最新の投稿
Привет, Andrey,

Нужно смотреть настройки Alfresco, вот есть хороший мануал по их политикам с разными кейсами:
https://www.alfresco.com/blogs/ewinlof/2013/03/11/introducing-the-new-csrf-filter-in-alfresco-share/