Expand my Community achievements bar.

Guidelines for the Responsible Use of Generative AI in the Experience Cloud Community.

RTMP NIO Server: Plugable Authentication?

Avatar

Level 1

How can I customise authentication for NIO RTMP on the serverside e.g. to use Spring Security?

I wasn't able to find anything in the manuals/doco except servlet-container stuff which isn't relevant.

Many Thanks,

Lee.

2 Replies

Avatar

Employee

Hey Lee, Spring support for our NIO channels is coming in our next release, but isn't available in 3.1.  Ping me offline if you're interested in joining our pre-release program.

Thanks!

Damon

(dcooper@adobe.com)

Avatar

Level 1

package flex.messaging.endpoints.filters;

public class AsyncSecurityContextFilter extends BaseAsyncMessageFilter {
            
    public AsyncSecurityContextFilter() {

    }

    @Override
    public void in(MessageContext context)
    {           
        if (FlexContext.getUserPrincipal() != null) {
            Assert.isInstanceOf(Authentication.class, FlexContext.getUserPrincipal(), "FlexContext.getUserPrincipal returned an unexpected type.  "
                + "Expected instance of " + Authentication.class.getName() + "but was " + FlexContext.getUserPrincipal().getName());
            SecurityContextHolder.getContext().setAuthentication((Authentication) FlexContext.getUserPrincipal());
        }       
        context.doIn(getNext());
    }

    @Override
    public void out(MessageContext context)
    {
        SecurityContextHolder.clearContext();

        context.doOut(getPrev());       
    }

    @Override
    public AsyncMessage filterPush(AsyncMessage message, FlexClient recipient, Endpoint endpoint) {
        return super.filterPush(message, recipient, endpoint);
    }
       
}

package org.springframework.flex;

public class MessageFilterConfigurationProcessor implements    MessageBrokerConfigProcessor
{   
    private List<BaseAsyncMessageFilter> asyncFilters;
    private List<BaseSyncMessageFilter> syncFilters;
   
    @Override
    public MessageBroker processAfterStartup(MessageBroker broker) {
        return broker;
    }

    @Override
    public MessageBroker processBeforeStartup(MessageBroker broker)
    {
        if (broker instanceof AsyncMessageBroker) {
            if (asyncFilters!=null)    {
                for (BaseAsyncMessageFilter asyncFilter : asyncFilters)    {
                    ((AsyncMessageBroker)broker).getAsyncMessageFilterChain().add(asyncFilter);                   
                    if (Log.isInfo()) {
                        Log.getLogger(ConfigurationManager.LOG_CATEGORY).info(
                                "MessageFilter '" + asyncFilter.getId() + "' of type '" + asyncFilter.getClass() + "' created.");
                    }
                }
            }
        }       
        return broker;
    }

    public void setAsyncFilters(List<BaseAsyncMessageFilter> asyncFilters) {
        this.asyncFilters = asyncFilters;
    }

    public void setSyncFilters(List<BaseSyncMessageFilter> syncFilters) {
        this.syncFilters = syncFilters;
    }

}

And the way you inject it into the filters chain is like this (spring-flex.xml)

    <bean id="messageBrokerFacebook" class="org.springframework.flex.core.MessageBrokerFactoryBean">
        <property name="beanName" value="messageBroker"/>
        <property name="configProcessors">
            <set>
                <ref local="messageFilterConfigProcessor"/>

                <!--any other pre/post processors you may want-->
            </set>
        </property>
    </bean>

    <bean id="messageFilterConfigProcessor" class="org.springframework.flex.MessageFilterConfigurationProcessor">
        <property name="asyncFilters">
            <list>
                <bean class="flex.messaging.endpoints.filters.AsyncSecurityContextFilter">
                    <property name="id" value="asyncSecurityFilter"/>
                </bean>
            </list>
        </property>
    </bean>