流媒体技术世界——分享技术,增值服务
如何采用服务端API对rtmp流的连接请求进行访问控制?

下面有三个例子详细描述了如何采用服务端API对RTMP流的连接请求进行访问控制




在netconnection.connect中参数传递用户名和密码,用文本文件存储用户名和密码

下面的代码例子展现了如何使用服务端API对RTMP流媒体播放请求进行访问控制,在这个例子中使用了一个基于文件的username/password认证方式。

Code:
package com.wowza.wms.plugin.collection.module;

import java.io.*;
import java.util.*;

import com.wowza.util.*;
import com.wowza.wms.amf.*;
import com.wowza.wms.application.*;
import com.wowza.wms.authentication.*;
import com.wowza.wms.authentication.file.*;
import com.wowza.wms.client.*;
import com.wowza.wms.module.*;
import com.wowza.wms.request.*;
import com.wowza.wms.util.*;
import com.wowza.wms.vhost.*;

public class ModuleOnConnectAuthenticate extends ModuleBase
{ 
	public static final String AUTHPASSWORDFILEPATH = "${com.wowza.wms.context.VHostConfigHome}/conf/connect.password";
	private File passwordFile = null;
	private String usernamePasswordProviderClass = null;

	public void onAppStart(IApplicationInstance appInstance)
	{
		getLogger().info("ModuleOnConnectAuthenticate started");
		WMSProperties props = appInstance.getProperties();
				
		String passwordFileStr = props.getPropertyStr("rtmpAuthenticateFile", AUTHPASSWORDFILEPATH);
		this.usernamePasswordProviderClass = props.getPropertyStr("usernamePasswordProviderClass", this.usernamePasswordProviderClass);
		if (passwordFileStr != null)
		{
			Map<String, String> envMap = new HashMap<String, String>();
			
			IVHost vhost = appInstance.getVHost();
			envMap.put("com.wowza.wms.context.VHost", vhost.getName());
			envMap.put("com.wowza.wms.context.VHostConfigHome", vhost.getHomePath());
			envMap.put("com.wowza.wms.context.Application", appInstance.getApplication().getName());
			envMap.put("com.wowza.wms.context.ApplicationInstance", appInstance.getName());

			passwordFileStr = SystemUtils.expandEnvironmentVariables(passwordFileStr, envMap);
			passwordFile = new File(passwordFileStr);
		}
		
		if (passwordFile != null)
			getLogger().info("ModuleOnConnectAuthenticate: Authorization password file: "+passwordFile.getAbsolutePath());
		if (usernamePasswordProviderClass != null)
			getLogger().info("ModuleOnConnectAuthenticate: Authorization password class: "+usernamePasswordProviderClass);
	}

		
	public void onConnect(IClient client, RequestFunction function, AMFDataList params)
	{
		boolean isAuthenticated = false;
		
		String allowedEncoder;
		Boolean isPublisher;
		
		String flashver = client.getFlashVer();
		getLogger().info("Flashver: " + flashver);
		
		try
		{
		allowedEncoder = client.getAppInstance().getProperties().getPropertyStr("AllowEncoder");
		isPublisher = flashver.startsWith(allowedEncoder); 
		
		if (isPublisher) 
		{
			client.acceptConnection();
			return;
		}
		}
		catch(Exception ex)
		{	
		}
		
		String username = null;
		String password = null;
		try
		{
			while(true)
			{
				if (params.size() <= PARAM2)
					break;
				
				username = params.getString(PARAM1);
				password = params.getString(PARAM2);
				
				if (username == null || password == null)
					break;
								
				IAuthenticateUsernamePasswordProvider filePtr = null;
				if (usernamePasswordProviderClass != null)
					filePtr = AuthenticationUtils.createUsernamePasswordProvider(usernamePasswordProviderClass);
				else if (passwordFile != null)
					filePtr = AuthenticationPasswordFiles.getInstance().getPasswordFile(passwordFile);
				
				if (filePtr == null)
					break;

				filePtr.setClient(client);

				String userPassword = filePtr.getPassword(username);
				if (userPassword == null)
					break;

				if (!userPassword.equals(password))
					break;
				
				isAuthenticated = true;
				break;
			}
		}
		catch(Exception e)
		{
			getLogger().error("ModuleOnConnectAuthenticate.onConnect: "+e.toString());
			isAuthenticated = false;
		}
		
		getLogger().info("ModuleOnConnectAuthenticate Authenticated: " + isAuthenticated);
		
		if (!isAuthenticated)
			client.rejectConnection("Authentication Failed["+client.getClientId()+"]: "+username);
		else
			client.acceptConnection();
	}
}
www.ttstream.com
这个模块的编译后的文件被包含在Wowza Modules Collection. 下载并解压缩后,将/lib/wms-plugin-collection.jar文件拷贝到Wowza /lib 目录下。然后重启Wowza Media Server。


这个模块的使用方法
  1. 在[install-dir]/conf目录下创建一个名字为connect.password的文本文件,然后为每一个用户在新的一行添加一对username和password(用空格分开):

    [install-dir]/conf/connect.password:
    user1 pass1
    user2 pass2
  2. 将下面的模块添加到需要认证的应用的Application.xml文件的模块集合中:

    Code:
    <Module> 
    <Name>moduleOnConnectAuthenticate</Name> 
    <Description>ModuleOnConnectAuthenticate</Description> 
    <Class>com.wowza.wms.plugin.collection.module.ModuleOnConnectAuthenticate</Class> 
    </Module>
  3. 在你的Flash应用程序中修改NetConnection.connect 部分的代码,传递一个username 和 password, 可能像下面的这样:
    Code:
    var username:String = "user1";
    var password = "pass1";
    netconnection.connect("rtmp://[wowza-address]/yourApp",username,password);


注意: 这个模块不支持Flash Media Live Encoder 和 Wirecast 的认证,它仅仅是对Flash应用程序在NetConnection.connect(rtmpURL, username, password)方法中传递的username和password进行认证,对于FMLE 或 Wirecast 风格的认证,请下载并安装MediaSecurity 插件包。

用url参数传递用户名和密码,用文本文件存储用户名和密码

下面的代码例子展现了如何使用服务端API对RTMP流媒体播放请求进行访问控制,在这个例子中使用了一个基于文件的username/password认证方式。

跟上面的例子不同,这里的用户名和密码仅仅被添加到connection的url中,而不是作为NetConnection.connect的参数。当有些编码器不支持username/password认证时,这个方法可以做为ModuleRTMPAuthenticate的替代方案。

Code:
package com.wowza.wms.plugin.collection.module;

import java.io.*;
import java.util.*;

import com.wowza.util.*;
import com.wowza.wms.amf.*;
import com.wowza.wms.application.*;
import com.wowza.wms.authentication.*;
import com.wowza.wms.authentication.file.*;
import com.wowza.wms.client.*;
import com.wowza.wms.module.*;
import com.wowza.wms.request.*;
import com.wowza.wms.util.*;
import com.wowza.wms.vhost.*;

public class ModuleOnConnectAuthenticate2 extends ModuleBase
{ 
	public static final String AUTHPASSWORDFILEPATH = "${com.wowza.wms.context.VHostConfigHome}/conf/connect.password";
	private File passwordFile = null;
	private String usernamePasswordProviderClass = null;

	public void onAppStart(IApplicationInstance appInstance)
	{
		WMSProperties props = appInstance.getProperties();
				
		String passwordFileStr = props.getPropertyStr("rtmpAuthenticateFile", AUTHPASSWORDFILEPATH);
		this.usernamePasswordProviderClass = props.getPropertyStr("usernamePasswordProviderClass", this.usernamePasswordProviderClass);
		if (passwordFileStr != null)
		{
			Map<String, String> envMap = new HashMap<String, String>();
			
			IVHost vhost = appInstance.getVHost();
			envMap.put("com.wowza.wms.context.VHost", vhost.getName());
			envMap.put("com.wowza.wms.context.VHostConfigHome", vhost.getHomePath());
			envMap.put("com.wowza.wms.context.Application", appInstance.getApplication().getName());
			envMap.put("com.wowza.wms.context.ApplicationInstance", appInstance.getName());

			passwordFileStr = SystemUtils.expandEnvironmentVariables(passwordFileStr, envMap);
			passwordFile = new File(passwordFileStr);
		}
		
		if (passwordFile != null)
			getLogger().info("ModuleOnConnectAuthenticate: Authorization password file: "+passwordFile.getAbsolutePath());
		if (usernamePasswordProviderClass != null)
			getLogger().info("ModuleOnConnectAuthenticate: Authorization password class: "+usernamePasswordProviderClass);
	}

public void onConnect(IClient client, RequestFunction function, AMFDataList params)
{
	boolean isAuthenticated = false;
	
	String username = null;
	String password = null;
	
	try
	{
		while(true)
		{
			getLogger().info("size: " + params.size());
			
			String[] auth = client.getQueryStr().split("&");
			
			username = auth[0];
			password = auth[1];
				
				if (username == null || password == null)
					break;
								
				IAuthenticateUsernamePasswordProvider filePtr = null;
				if (usernamePasswordProviderClass != null)
					filePtr = AuthenticationUtils.createUsernamePasswordProvider(usernamePasswordProviderClass);
				else if (passwordFile != null)
					filePtr = AuthenticationPasswordFiles.getInstance().getPasswordFile(passwordFile);
				
				if (filePtr == null)
					break;

				filePtr.setClient(client);

				String userPassword = filePtr.getPassword(username);
				if (userPassword == null)
					break;

				if (!userPassword.equals(password))
					break;
				
				isAuthenticated = true;
				break;
			}
		}
		catch(Exception e)
		{
			getLogger().error("ModuleOnConnectAuthenticate.onConnect: "+e.toString());
			isAuthenticated = false;
		}
		
		if (!isAuthenticated)
			client.rejectConnection("Authentication Failed["+client.getClientId()+"]: "+username);
		else
			client.acceptConnection();
	}
}
编译后的模块包含在Wowza Modules 集合中。 下载并解开压缩包,将/lib/wms-plugin-collection.jar文件拷贝到Wowza /lib 文件夹下。然后重启Wowza Media Server。

这个模块的使用方法
  1. 在[install-dir]/conf文件夹下创建一个文本文件,命名为connect.password,在每个新的一行添加一个用户名和密码(用空格分割开):

    [install-dir]/conf/connect.password:
    user1 pass1
    user2 pass2
  2. 将下面的模块添加到需要认证的应用的Application.xml文件的模块列表中:

    Code:
    <Module> 
    <Name>moduleOnConnectAuthenticate2</Name> 
    <Description>ModuleOnConnectAuthenticate2</Description> 
    <Class>com.wowza.wms.plugin.collection.module.ModuleOnConnectAuthenticate2</Class> 
    </Module>
  3. 在你的Flash应用代码中,修改NetConnection.connect部分,如下:
    Code:
    netconnection.connect("rtmp://[wowza-address]/[app-name]?user1&pass1");


用url参数传递用户名和密码,用Mysql数据库存储用户名和密码

这个例子使用MySQL数据存储用户名和密码。

  1. 下载官方的JDBC driver for MySQL.

  2. 解压缩下载包后,将mysql-connector-java-5.0.5-bin.jar 拷贝到Wowza的安装路径的[install-dir]/lib下。

    服务端Java代码类似如下:
    Code:
    package com.mycompany.wms.dbtest;
    
    import java.sql.*;
    
    import com.wowza.wms.application.*;
    import com.wowza.wms.amf.*;
    import com.wowza.wms.client.*;
    import com.wowza.wms.module.*;
    import com.wowza.wms.request.*;
    
    public class DBTest extends ModuleBase 
    {
    	public void onAppStart(IApplicationInstance appInstance)
    	{
    		// preload the driver class
    		try 
    		{
    			Class.forName("com.mysql.jdbc.Driver").newInstance(); 
    		} 
    		catch (Exception e) 
    		{ 
    			getLogger().error("Error loading: com.mysql.jdbc.Driver: "+e.toString());
    		} 
    	}
    
    	public void onConnect(IClient client, RequestFunction function, AMFDataList params) 
    	{
    		
    		String userName = getParamString(params, PARAM1);
    		String password = getParamString(params, PARAM2);
    
    		
    		Connection conn = null;
    		try 
    		{
    			conn = DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb");
    
    			Statement stmt = null;
    			ResultSet rs = null;
    
    			try 
    			{
    				stmt = conn.createStatement();
    				rs = stmt.executeQuery("SELECT count(*) as userCount FROM users where username = '"+userName+"' and password = '"+password+"'");
    				if (rs.next() == true)
    				{
    				    if (rs.getInt("userCount") > 0)
    					{
    						client.acceptConnection();
    					}
    				}
    
    			} 
    			catch (SQLException sqlEx) 
    			{
    				getLogger().error("sqlexecuteException: " + sqlEx.toString());
    			} 
    			finally 
    			{
    				// it is a good idea to release
    				// resources in a finally{} block
    				// in reverse-order of their creation
    				// if they are no-longer needed
    
    				if (rs != null) 
    				{
    					try 
    					{
    						rs.close();
    					} 
    					catch (SQLException sqlEx) 
    					{
    
    						rs = null;
    					}
    				}
    
    				if (stmt != null) 
    				{
    					try 
    					{
    						stmt.close();
    					} 
    					catch (SQLException sqlEx) 
    					{
    						stmt = null;
    					}
    				}
    			}
    
    			conn.close();
    		} 
    		catch (SQLException ex) 
    		{
    			// handle any errors
    			System.out.println("SQLException: " + ex.getMessage());
    			System.out.println("SQLState: " + ex.getSQLState());
    			System.out.println("VendorError: " + ex.getErrorCode());
    		}
    
    		getLogger().info("onConnect: " + client.getClientId());
    	}
    
    	static public void onConnectAccept(IClient client) 
    	{
    		getLogger().info("onConnectAccept: " + client.getClientId());
    	}
    
    	static public void onConnectReject(IClient client) 
    	{
    		getLogger().info("onConnectReject: " + client.getClientId());
    	}
    
    	static public void onDisconnect(IClient client) 
    	{
    		getLogger().info("onDisconnect: " + client.getClientId());
    	}
    
    }
  3. 编辑Application.xml文件,在<Modules>列表中添加这个模块,然后将Connections/AutoAccept 设置为 false.

匿名用户
评论

我们的地址


北京市朝阳区管庄西里建基商务楼423室


邮编:100024

关于我们


北京联方信科信息技术有限责任公司


官网:www.ttstream.com

联系我们


王经理:phone


柳经理:phone

京ICP备14033868号-2