1. 用url参数传递用户名和密码,用文本文件存储用户名和密码
下面的代码例子展现了如何使用服务端API对RTMP流媒体播放请求进行访问控制,在这个例子中使用了一个基于文件的username/password认证方式。
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 Streaming Engine。
这个模块的使用方法
-
在[install-dir]/conf文件夹下创建一个文本文件,命名为connect.password,在每个新的一行添加一个用户名和密码(用空格分割开):
[install-dir]/conf/connect.password:
user1 pass1 user2 pass2
-
将下面的模块添加到需要认证的应用的Application.xml文件的模块列表中:
<Module> <Name>moduleOnConnectAuthenticate2</Name> <Description>ModuleOnConnectAuthenticate2</Description> <Class>com.wowza.wms.plugin.collection.module.ModuleOnConnectAuthenticate2</Class> </Module>
2. 用url参数传递用户名和密码,用Mysql数据库存储用户名和密码
这个例子使用MySQL数据存储用户名和密码。
- 下载官方的JDBC driver for MySQL.
- 解压缩下载包后,将mysql-connector-java-5.0.5-bin.jar 拷贝到Wowza的安装路径的[install-dir]/lib下。
服务端Java代码类似如下:
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()); } }
- 编辑Application.xml文件,在<Modules>列表中添加这个模块,然后将Connections/AutoAccept 设置为 false.