Red5集成Spring MVC并验证简单防盗链机制
上篇文章我们实现了创建Red5项目并实现自定义逻辑,这篇文章介绍如何将项目转为Maven项目并集成Spring MVC框架
转为Maven项目
-
将Red5-live项目Convert为Maven项目
选中当前项目右键->Configure->Convert to Maven Project,默认或者做简单修改之间点击Finish
生成pom文件及target文件夹
-
创建Maven项目标准目录
先将原来的src目录删掉提前保存好src目录下的文件
新建Source Folder,分别为src/main/java、src/main/resources、src/test/java,然后创建org.red5.examples包,将事先编写好的Application类复制到该包下
-
创建webapp目录替换原来的WebContent
在src/main目录下创建Folder,命名为webapp,然后将WebContent目录下的文件复制到webapp目录下,并将WebContent目录删除
-
pom文件引入相关依赖
这里我是直接将以后可能用到的依赖全部导入了,可能有些用不到自行删除,导入了也没啥影响,不过需要注意的是spring版本需要同red5-server中的spring版本相同。
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <swagger.version>2.7.0</swagger.version> <shiro.version>1.4.0</shiro.version> <junit.version>4.10</junit.version> <spring.version>4.3.5.RELEASE</spring.version> <mybatis.version>3.2.8</mybatis.version> <mybatis.spring.version>1.2.2</mybatis.spring.version> <mybatis.paginator.version>1.2.15</mybatis.paginator.version> <mysql.version>8.0.12</mysql.version> <slf4j.version>1.6.4</slf4j.version> <jackson.version>2.6.0</jackson.version> <druid.version>1.0.9</druid.version> <httpclient.version>4.5.2</httpclient.version> <jstl.version>1.2</jstl.version> <servlet-api.version>2.5</servlet-api.version> <jsp-api.version>2.0</jsp-api.version> <commons-lang3.version>3.7</commons-lang3.version> <commons-io.version>1.3.2</commons-io.version> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <quartz.version>2.3.0</quartz.version> <kaptcha.version>0.0.9</kaptcha.version> <qiniu.version>7.2.23</qiniu.version> <aliyun.oss.version>2.5.0</aliyun.oss.version> <qcloud.cos.version>4.4</qcloud.cos.version> <servlet-api.version>3.1.0</servlet-api.version> <lombok.version>1.18.4</lombok.version> <jedis.version>2.9.1</jedis.version> <hibernate-validator.version>6.0.16.Final</hibernate-validator.version> <validation-api.version>2.0.1.Final</validation-api.version> <mybatis-plus.version>3.3.0</mybatis-plus.version> <joda-time.version>2.10.3</joda-time.version> <spring-data-redis.version>1.6.2.RELEASE</spring-data-redis.version> <shiro-ehcache.version>1.2.4</shiro-ehcache.version> <thymeleaf-extras-shiro.version>2.0.0</thymeleaf-extras-shiro.version> <freemarker.version>2.3.23</freemarker.version> <shiro-freemarker-tags.version>0.1</shiro-freemarker-tags.version> <server-sdk-java.version>3.1.6</server-sdk-java.version> <pagehelper.version>3.7.5</pagehelper.version> <spring-rabbit.version>1.4.0.RELEASE</spring-rabbit.version> <bonecp-spring.version>0.8.0.RELEASE</bonecp-spring.version> <commons-fileupload.version>1.3.1</commons-fileupload.version> <mapper.version>2.3.4</mapper.version> <alipay-sdk-java.version>3.1.0</alipay-sdk-java.version> <druid.version>1.1.13</druid.version> <poi-ooxml.version>4.1.2</poi-ooxml.version> </properties> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> <!-- Jackson Json处理工具包 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet-api.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!-- Apache工具组件 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>${commons-io.version}</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${jedis.version}</version> </dependency> <!-- httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>${httpclient.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency>--> <!-- use hibernate-validator to validate entity before enter controller --> <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate-validator.version}</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>${validation-api.version}</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>${mybatis-plus.version}</version> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>${joda-time.version}</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>${spring-data-redis.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <!-- 引入ehcache的依赖,给shiro做缓存权限用的 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>${shiro-ehcache.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>${thymeleaf-extras-shiro.version}</version> </dependency> <!--添加freemarker依赖--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>${freemarker.version}</version> </dependency> <dependency> <groupId>net.mingsoft</groupId> <artifactId>shiro-freemarker-tags</artifactId> <version>${shiro-freemarker-tags.version}</version> </dependency> <dependency> <groupId>cn.rongcloud.im</groupId> <artifactId>server-sdk-java</artifactId> <version>${server-sdk-java.version}</version> <exclusions> <exclusion> <artifactId>junit</artifactId> <groupId>junit</groupId> </exclusion> </exclusions> </dependency> <!-- 分页助手 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pagehelper.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> <version>${spring-rabbit.version}</version> </dependency> <!-- MySql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- 连接池 --> <dependency> <groupId>com.jolbox</groupId> <artifactId>bonecp-spring</artifactId> <version>${bonecp-spring.version}</version> </dependency> <!-- JSP相关 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> </dependency> <!--文件上传组件--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons-fileupload.version}</version> </dependency> <!-- Mybatis --> <!-- 通用Mapper --> <dependency> <groupId>com.github.abel533</groupId> <artifactId>mapper</artifactId> <version>${mapper.version}</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>${quartz.version}</version> <exclusions> <exclusion> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> </exclusion> <exclusion> <groupId>com.zaxxer</groupId> <artifactId>HikariCP-java6</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.github.axet</groupId> <artifactId>kaptcha</artifactId> <version>${kaptcha.version}</version> </dependency> <dependency> <groupId>com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> <version>${qiniu.version}</version> </dependency> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>${aliyun.oss.version}</version> <exclusions> <exclusion> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>${qcloud.cos.version}</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </exclusion> <exclusion> <artifactId>junit</artifactId> <groupId>junit</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>${alipay-sdk-java.version}</version> </dependency> <!--<dependency>--> <!--<groupId>org.apache.poi</groupId>--> <!--<artifactId>poi-ooxml</artifactId>--> <!--<version>${poi-ooxml.version}</version>--> <!--</dependency>--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.6</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <build> <finalName>frame</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build>
-
配置相关配置文件
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <!-- The display-name element contains a short name that is intended to be displayed by tools. The display name need not be unique. --> <display-name>red5-live</display-name> <!-- The context-param element contains the declaration of a web application's servlet context initialization parameters. --> <context-param> <param-name>webAppRootKey</param-name> <param-value>/red5-live</param-value> </context-param> <listener> <listener-class>org.red5.logging.ContextLoggingListener</listener-class> </listener> <filter> <filter-name>LoggerContextFilter</filter-name> <filter-class>org.red5.logging.LoggerContextFilter</filter-class> </filter> <filter-mapping> <filter-name>LoggerContextFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- remove the following servlet tags if you want to disable remoting for this application --> <servlet> <servlet-name>gateway</servlet-name> <servlet-class> org.red5.server.net.servlet.AMFGatewayServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- The servlet-mapping element defines a mapping between a servlet and a url pattern --> <servlet-mapping> <servlet-name>gateway</servlet-name> <url-pattern>/gateway</url-pattern> </servlet-mapping> <!-- The security-constraint element is used to associate security constraints with one or more web resource collections --> <security-constraint> <web-resource-collection> <web-resource-name>Forbidden</web-resource-name> <url-pattern>/streams/*</url-pattern> </web-resource-collection> <auth-constraint/> </security-constraint> <!-- 编码过滤器,以UTF8编码 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置SpringMVC框架入口 --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <!-- 可行:/、*.xxx、/xxx/* 不行:/* --> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>/index.html</welcome-file> </welcome-file-list> </web-app>
red5-web.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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-2.5.xsd"> <!-- Defines a properties file for dereferencing variables --> <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="/WEB-INF/red5-web.properties" /> </bean> <!-- Defines the web context --> <bean id="web.context" class="org.red5.server.Context" autowire="byType" /> <!-- Defines the web scopes --> <bean id="web.scope" class="org.red5.server.scope.WebScope" init-method="register"> <property name="server" ref="red5.server" /> <property name="parent" ref="global.scope" /> <property name="context" ref="web.context" /> <property name="handler" ref="web.handler" /> <property name="contextPath" value="${webapp.contextPath}" /> <property name="virtualHosts" value="${webapp.virtualHosts}" /> </bean> <!-- Defines the web handler which acts as an applications endpoint --> <bean id="web.handler" class="org.red5.examples.Application" /> <bean id="dispatcher" class="org.springframework.web.servlet.DispatcherServlet" /> <!-- Import your MVC servlet context xml and ensure the name matches the referenced servlet in your web.xml file. In this example, the name used is "dispatcher". --> <import resource="classpath:springmvc.xml"/> </beans>
red5-web.properties
webapp.contextPath=/red5-live webapp.virtualHosts=*
在resources目录下创建springmvc.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.red5.examples.springmvc.controller" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> </beans>
-
修改Maven Web项目的发布项
选中项目,点击上方菜单栏中的project,点击properties->Deployment Assembly,按照下面进行配置
-
运行,如果出现下列打印信息则项目启动正常
-
验证Spring MVC是否集成成功
编写BaseController类
package org.red5.examples.controller; import java.rmi.server.UID; import java.util.Base64; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import org.red5.logging.Red5LoggerFactory; import org.slf4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class BaseController { private static Logger log = Red5LoggerFactory.getLogger(BaseController.class, "oflaDemo"); private static final String VIEW_INDEX = "index"; private static final String VIEW_URLPARAM = "urlParam"; private static int counter = 0; @RequestMapping(value = "/", method = RequestMethod.GET) public String welcome(ModelMap model) { model.addAttribute("message", "Welcome"); model.addAttribute("counter", ++counter); log.debug("[welcome] counter : {}", counter); // Spring uses InternalResourceViewResolver and return back index.jsp return VIEW_INDEX; } @RequestMapping(value = "/{name}", method = RequestMethod.GET) public String welcomeName(@PathVariable String name, ModelMap model) { model.addAttribute("message", "Welcome " + name); model.addAttribute("counter", ++counter); log.debug("[welcomeName] counter : {}", counter); return VIEW_INDEX; } }
index.jsp
<html> <body> <h1>Hello World</h1> </body> </html>
Red5实现防盗链
对一个直播点播系统来说,其中一个非常重要的功能就是防盗链,这样就可以避免他人滥用链接观看直播或者点播内容,防盗链的实现方式有多种,这是使用添加防盗链参数的方式来时防盗链功能,根据秘钥和需要的防盗链参数生成防盗链token返回给客户端,客户端拉流时携带该token由服务端进行验证token合法性判断时候允许拉流。
防盗链参数
字段 | 是否必选 | 说明 |
---|---|---|
time | 是 | 过期时间 |
dir | 是 | 文件目录 |
uid | 否 | 唯一标识符 |
exper | 否 | 播放时长 |
具体实现
生成token并加密
@RequestMapping(value = "/url/Param", method = RequestMethod.GET)
public String urlParam(ModelMap model) {
Date date = new Date();
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
calendar.add(Calendar.HOUR,1);
//生成过期时间
Long time = calendar.getTimeInMillis();
//文件目录
String dirString = "/oflaDemo/";
//随机字符串
String uidString = "12ssww";
//拼接token
String urlParam = time+":"+dirString+":"+uidString;
//加密
urlParam = new String(DESUtils.encrypt(urlParam.getBytes(), DESUtils.Key));
model.addAttribute("urlParam", urlParam);
model.addAttribute("time", +new Date().getTime());
log.debug("[welcomeName] counter : {}", counter);
return VIEW_URLPARAM;
}
<html>
<body>
<h1>Param</h1>
<h2>urlParam : ${urlParam}</h2>
<h2>createTime: ${time}</h2>
</body>
</html>
拉流前验证合法性,在Apllication类
public void streamSubscriberStart(ISubscriberStream stream) {
System.out.println("[streamSubscriberStart]********** ");
System.out.println("播放:" + stream.getScope().getContextPath());
System.out.println("播放Key:" + stream.getBroadcastStreamPublishName());
System.out.println("********************************* ");
String sessionId = stream.getConnection().getSessionId();
stream.getConnection().setAttribute(null, null);
System.out.println("sessionId"+sessionId);
String path = stream.getConnection().getPath();
String address = stream.getConnection().getRemoteAddress();
System.out.println("address"+address);
System.out.println("path"+path);
//验证token合法性
String param = (String) stream.getConnection().getConnectParams().get("queryString");
System.out.println("param"+param);
System.out.println("********************************* "+stream.getConnection().getHost());
if(param!=null) {
System.out.println(param);
String[] strs = param.split("\\?");
for (String string : strs) {
System.out.println(string);
}
String params = null;
try {
params = new String(DESUtils.decrypt(strs[1].getBytes(), DESUtils.Key));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(params);
//验证是否合法
}else {
stream.getConnection().close();
System.out.println("被拒绝!");
}
super.streamSubscriberStart(stream);
}
最终结果:1597227868006:/oflaDemo/:12ssww
验证成功!
整合好的项目:https://download.csdn.net/download/qq_41345281/12709144