简体   繁体   中英

How to control key generation in Mule Cache

My requirement is to authenticate the user (with an external ws) as part of my Mule Flow and use the result of the authentication in a cache. however, if the user credentials change, then the cache should be automatically invalidated and user auth must be done with the external ws. Basically the cache key should be based on the user credentials. Is this possible ?

Here's my mule flow and i see that Mule is caching the results after the first request and irrespective of whether or not the payload changes in subsequent requests ( which is where the credentials are sent ) mule always returns the results from the cache. So when the first request has incorrect credentials, user auth fails and mule caches the response. From this point onwards, irrespective of sending correct credentials in subsequent requests, it always refers to the cache and returns user auth failure. How do I achieve what I wanted to achieve ?

Here's my mule flow:

    <?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
    xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.6.0"
    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-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd">
    <http:listener-config name="HTTP-Inbound-Endpoint" host="0.0.0.0" port="8888" doc:name="HTTP Listener Configuration"/>
    <http:request-config name="HTTP_Request_Configuration" host="10.10.10.10" port="8080" doc:name="HTTP Request Configuration"/>
    <ee:object-store-caching-strategy name="Auth-Cache-Strategy" doc:name="Caching Strategy">
        <in-memory-store name="UserAuthCache" maxEntries="100" entryTTL="3600" expirationInterval="3600"/>
    </ee:object-store-caching-strategy>
    <flow name="cacheauthenticationFlow">
        <http:listener config-ref="HTTP-Inbound-Endpoint" path="*" doc:name="HTTP"/>
        <object-to-string-transformer doc:name="Object to String"/>
        <ee:cache cachingStrategy-ref="Auth-Cache-Strategy" doc:name="Cache">
            <logger message="Incoming: #[message.payload]" level="INFO" doc:name="Logger"/>
            <scripting:transformer doc:name="Python">
                <scripting:script engine="jython"><![CDATA[import base64
authorization = message.getInboundProperty("authorization")
#print "Authorization is: \"" + authorization + "\""
authstring = authorization.split()
#print authstring
credentials = authstring[-1]
#print "Credentials => " + credentials

decodedAuth = credentials.decode('base64')
#print decodedAuth
if (decodedAuth.find("@") > 0):
    (id, password) = decodedAuth.split(":")
    (username, project) = id.split("@")
    print username + ":" + password + ", Project: " + project
else:
    (username, password) = decodedAuth.split(":")
    print username + ":" + password

message.payload = { "username" : username + "@" + project , "password" : password }
result = message]]></scripting:script>
            </scripting:transformer>
            <json:object-to-json-transformer doc:name="Object to JSON"/>
            <logger message="Incoming payload: #[message.payload]" level="INFO" doc:name="Logger"/>
            <http:request config-ref="HTTP_Request_Configuration" path="/wservices/authenticate/user" method="POST" doc:name="HTTP-Dev-Box-Authentication"/>
            <object-to-string-transformer doc:name="Object to String"/>
        </ee:cache>
        <logger message="Response From Cache: #[message.payload]" level="INFO" doc:name="Logger"/>
        <set-payload value="#[message.payload.'status']" doc:name="Response"/>
    </flow>
</mule>

Since the default key generation strategy for the cache scope is based on the message payload an option in your particular case would be to simply move the scripting:transformer to be executed before the ee:cache scope.

For a more general solution, where you do not want to overwrite your request payload, you can define the keyGenerationExpression or keyGenerator-ref attribute on the ee:cache element to control how the cache key i generated.

For example to use the complete HTTP authorization header as key you could use:

 <ee:cache cachingStrategy-ref="Auth-Cache-Strategy" doc:name="Cache"
      keyGenerationExpression="#[message.inboundProperties.authorization]">
     <!-- Your flow here --> 
 </ee:cache>

See the cache scope documentation for more information.

If you want to use this approach you could do is move parts of your jython code outside the cache scope, change it so that it sets the user and password as separate flow variables on the message and then use them in the keyGenerationExpression and then again later inside the cache scope in a simple set-payload transformer.

You can define a global configuration "Caching_Strategy" :

<ee:object-store-caching-strategy name="Caching_Strategy" keyGenerationExpression="#[flowVars.userID]" doc:name="Caching Strategy"/>

and refer the global configuration in cache flow:

<ee:cache doc:name="Cache" cachingStrategy-ref="Caching_Strategy">
<!-- flow -->
</ee:cache>

You can control your keyGenerationExpression by the flow variable #[flowVars.userID]

For complete detail with example refer http://www.tutorialsatoz.com/caching-in-mule-cache-scope/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM