Java 阿里云视频直播开发流程

首先来看一下直播效果 推流工具有很多种(例如OBS、阿里云直播Demo推流、等等,我用的是芯象导播)阿里播放器地址
在这里插入图片描述

一、直播基础服务概述 官方文档说明
在这里插入图片描述
在这里插入图片描述
二、直播域名配置需要两个域名(推流域名、播流域名) 官方文档说明
在这里插入图片描述
在这里插入图片描述
四、开发流程
1、Java SDK安装 我用的是Apache Maven安装方式 官方安装说明文档
在这里插入图片描述
2、Java代码生成推流地址和播放地址 官方案例

package com.zaiyun.zhibo.utils;import com.zaiyun.common.core.domain.model.User;
import com.zaiyun.common.utils.DateUtils;
import com.zaiyun.common.utils.SecurityUtils;
import com.zaiyun.zhibo.domain.LiveRooms;
import org.springframework.stereotype.Component;import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;/*** 阿里视频直播工具类*/
@Component
public class LiveUtils {/*** 生成推流地址** @param appName    推流AppName* @param streamName 推流StreamName*/public static String buildPushUrl(String appName, String streamName) {String pushDomain = "zyt.*****.com"; //推流域名String pushKey = "2T39rSP2dVro";//推流域名配置的鉴权KeyString pushUrl = "";//推流域名未开启鉴权功能的情况下if (pushKey == "") {pushUrl = "rtmp://" + pushDomain + "/" + appName + "/" + streamName;} else {Long timeStamp = System.currentTimeMillis() / 1000L + 3601L;String stringToMd5 = "/" + appName + "/" + streamName + "-" + Long.toString(timeStamp) + "-0-0-" + pushKey;String authKey = md5(stringToMd5);pushUrl = "rtmp://" + pushDomain + "/" + appName + "/" + streamName + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + authKey;}return pushUrl;}/*** 生成播放地址** @param appName    播放appName(同推流appName)* @param streamName 播放streamName,播放源流时,streamName 同推流streamName;播放转码流时,streamName 为推流streamName_{转码模板ID}*/public static HashMap<String, String> buildPullUrl(String appName, String streamName) {String pullDomain = "zyb.*****.com"; //播放域名String pullKey = "92KiuYjNYr5H"; //播放鉴权KeyString rtmpUrl = ""; //rtmp的拉流地址String hlsUrl = ""; //m3u8的拉流地址String flvUrl = ""; //flv的拉流地址String rtsUrl = ""; //rts的拉流地址//播放域名未配置鉴权Key的情况下if (pullKey == "") {rtmpUrl = "rtmp://" + pullDomain + "/" + appName + "/" + streamName;rtsUrl = "artc://" + pullDomain + "/" + appName + "/" + streamName;hlsUrl = "http://" + pullDomain + "/" + appName + "/" + streamName + ".m3u8";flvUrl = "http://" + pullDomain + "/" + appName + "/" + streamName + ".flv";} else {Long timeStamp = System.currentTimeMillis() / 1000L + 3600L;String rtmpToMd5 = "/" + appName + "/" + streamName + "-" + Long.toString(timeStamp) + "-0-0-" + pullKey;String rtmpAuthKey = md5(rtmpToMd5);rtmpUrl = "rtmp://" + pullDomain + "/" + appName + "/" + streamName + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + rtmpAuthKey;String hlsToMd5 = "/" + appName + "/" + streamName + ".m3u8-" + Long.toString(timeStamp) + "-0-0-" + pullKey;String hlsAuthKey = md5(hlsToMd5);hlsUrl = "http://" + pullDomain + "/" + appName + "/" + streamName + ".m3u8" + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + hlsAuthKey;String flvToMd5 = "/" + appName + "/" + streamName + ".flv-" + Long.toString(timeStamp) + "-0-0-" + pullKey;String flvAuthKey = md5(flvToMd5);flvUrl = "http://" + pullDomain + "/" + appName + "/" + streamName + ".flv" + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + flvAuthKey;String rtsToMd5 = "/" + appName + "/" + streamName + "-" + Long.toString(timeStamp) + "-0-0-" + pullKey;String rtsAuthKey = md5(rtsToMd5);rtsUrl = "artc://" + pullDomain + "/" + appName + "/" + streamName + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + rtsAuthKey;}HashMap<String, String> url = new HashMap<>();url.put("rtmpUrl", rtmpUrl);url.put("hlsUrl", hlsUrl);url.put("flvUrl", flvUrl);url.put("rtsUrl", rtsUrl);return url;}/*** 计算md5*/public static String md5(String param) {if (param == null || param.length() == 0) {return null;}try {MessageDigest md5 = MessageDigest.getInstance("MD5");md5.update(param.getBytes());byte[] byteArray = md5.digest();BigInteger bigInt = new BigInteger(1, byteArray);// 参数16表示16进制String result = bigInt.toString(16);// 不足32位高位补零while (result.length() < 32) {result = "0" + result;}return result;} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return null;}/*** 登录需的要鉴权信息*/public static HashMap<String, Object> appAuth(LiveRooms room) {String role = "";User user = SecurityUtils.getLoginUser().getUser();String userId = user.getUserId().toString();String appId = room.getAppId();String appKey = room.getAppKey();String appSign = room.getAppSign();String nonce = java.util.UUID.randomUUID().toString();Long timestamp = DateUtils.addHours(new Date(), 1).getTime() / 1000;String signContent = String.format("%s%s%s%s%s%s", appId, appKey, userId, nonce, timestamp, role);String appToken = org.apache.commons.codec.digest.DigestUtils.sha256Hex(signContent);HashMap<String, Object> result = new HashMap<>();result.put("appId", appId);result.put("appSign", appSign);result.put("appToken", appToken);result.put("role", role);result.put("nonce", nonce);result.put("userId", userId);result.put("timestamp", timestamp);result.put("userName", user.getUserName());return result;}
}

在这里插入图片描述
3、直播间互动功能(消息组)

package com.zaiyun.zhibo.controller;import com.zaiyun.common.annotation.Anonymous;
import com.zaiyun.common.core.controller.BaseController;
import com.zaiyun.common.core.domain.AjaxResult;
import com.zaiyun.zhibo.domain.LiveRooms;
import com.zaiyun.zhibo.mapper.LiveRoomsMapper;
import com.zaiyun.zhibo.utils.LiveAppUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.HashMap;/*** 最新版本的消息组*/
@Anonymous
@RestController
@RequestMapping("/live/app")
public class LiveAppController extends BaseController {@ResourceLiveAppUtils liveAppUtils;@ResourceLiveRoomsMapper liveRoomsMapper;/*** 创建互动消息应用*/@PostMapping("/create")public AjaxResult createMessageApp() {try {String appName = "myApp";return success(liveAppUtils.createMessageApp(appName));} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}/*** 获取互动消息应用*/@PostMapping("/list")public AjaxResult getMessageAppList() {try {return success(liveAppUtils.getMessageAppList());} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}/*** 获取互动消息应用详情*/@PostMapping("/info")public AjaxResult getMessageAppInfo() {try {String appId = "abc13a82b773";return success(liveAppUtils.getMessageAppInfo(appId));} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}/*** 创建消息组*/@PostMapping("/group/create")public AjaxResult createMessageGroup() {try {String appId = "abc13a82b773";return success(liveAppUtils.createMessageGroup(appId));} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}/*** 查询指定用户下消息组列表*/@PostMapping("/group/list")public AjaxResult listMessageGroup() {try {String appId = "abc13a82b773";return success(liveAppUtils.listMessageGroup(appId));} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}/*** 消息组详情*/@PostMapping("/group/describe")public AjaxResult groupDescribe() {try {HashMap<String, String> parameter = new HashMap<>();parameter.put("appId", "abc13a82b773");parameter.put("groupId", "211a39c8-2ebd-4d4b-978e-dfa31836220f");return success(liveAppUtils.groupDescribe(parameter));} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}/*** 发送消息到群组*/@PostMapping("/send/group")public AjaxResult sendMessageGroup(@RequestBody HashMap<String, String> data) {try {String roomId = data.get("roomId");String msgType = data.get("msgType");String body = data.get("body");if (roomId == null || msgType == null || body == null) {return AjaxResult.error(201, "参数错误 roomId 或 msgType 或 body");}LiveRooms liveRooms = new LiveRooms();liveRooms.setId(Integer.parseInt(roomId));LiveRooms room = liveRoomsMapper.findRoomByWhere(liveRooms);HashMap<String, String> parameter = new HashMap<>();parameter.put("appId", room.getAppId());parameter.put("groupId", room.getGroupId());parameter.put("senderId", "admin" + getUserId());//发送者parameter.put("msgType", msgType);//消息类型parameter.put("body", body);//消息内容return success(liveAppUtils.sendMessageGroup(parameter));} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}/*** 发送消息到用户*/@PostMapping("/send/user")public AjaxResult sendMessageUser() {try {HashMap<String, String> parameter = new HashMap<>();parameter.put("appId", "abc13a82b773");parameter.put("senderId", "uid10");//发送者parameter.put("receiverId", "100");//接收者parameter.put("body", "{\"content\":\"这里是发送的消息内容!\"}");//消息内容return success(liveAppUtils.sendMessageUser(parameter));} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}/*** 查询群组消息列表*/@PostMapping("/group/messages")public AjaxResult getGroupMessages() {try {HashMap<String, String> parameter = new HashMap<>();parameter.put("appId", "abc13a82b773");parameter.put("groupId", "211a39c8-2ebd-4d4b-978e-dfa31836220f");return success(liveAppUtils.getGroupMessages(parameter));} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}/*** 查询群组用户列表*/@PostMapping("/group/users")public AjaxResult getGroupUsers() {try {HashMap<String, String> parameter = new HashMap<>();parameter.put("appId", "abc13a82b773");parameter.put("groupId", "211a39c8-2ebd-4d4b-978e-dfa31836220f");return success(liveAppUtils.getGroupUsers(parameter));} catch (Exception e) {return AjaxResult.error(201, e.getMessage());}}
}
package com.zaiyun.zhibo.utils;import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.live.model.v20161101.*;
import com.aliyuncs.profile.DefaultProfile;
import com.zaiyun.common.config.AlibabaConfig;
import com.zaiyun.common.utils.uuid.UUID;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.HashMap;/*** 阿里视频直播工具类*/
@Component
public class LiveAppUtils {/*** 初始化配置*/public static IAcsClient createClient() throws Exception {DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", AlibabaConfig.getAccessKeyId(), AlibabaConfig.getAccessKeySecret());return new DefaultAcsClient(profile);}/*** 创建互动消息应用** @param appName 互动消息应用名称,长度 2~16 个字符*/public static CreateLiveMessageAppResponse createMessageApp(String appName) throws Exception {IAcsClient client = createClient();CreateLiveMessageAppRequest request = new CreateLiveMessageAppRequest();request.setAppName(appName);request.setAuditType(1);//内置安全审核try {return client.getAcsResponse(request);} catch (ClientException error) {throw new RuntimeException("创建互动消息应用异常!" + error);}}/*** 查询互动消息应用列表*/public static Object getMessageAppList() throws Exception {IAcsClient client = createClient();ListLiveMessageAppsRequest request = new ListLiveMessageAppsRequest();request.setSortType(1);try {return client.getAcsResponse(request);} catch (ClientException error) {throw new RuntimeException("查询互动消息应用列表异常!" + error);}}/*** 查询互动消息应用详情*/public static Object getMessageAppInfo(String appId) throws Exception {IAcsClient client = createClient();DescribeLiveMessageAppRequest request = new DescribeLiveMessageAppRequest();request.setAppId(appId);try {return client.getAcsResponse(request);} catch (ClientException error) {throw new RuntimeException("查询互动消息应用详情异常!" + error);}}/*** 创建消息组** @param appId 互动消息应用ID*/public static String createMessageGroup(String appId) throws Exception {IAcsClient client = createClient();CreateLiveMessageGroupRequest request = new CreateLiveMessageGroupRequest();request.setAppId(appId);request.setCreatorId("admin1");//群组创建者ID。request.setDataCenter("cn-shanghai");//数据中心request.setGroupInfo("testgroupinfo");//群组扩展信息,最大512字符。request.setGroupId(UUID.fastUUID().toString());//要创建的群组ID,由大小写字母、数字组成,最大64字符。request.setGroupName(RandomStringUtils.randomAlphanumeric(10));//群组名,最大64字符。ArrayList<String> administrators = new ArrayList<>();administrators.add("aaaaa");administrators.add("bbbbb");administrators.add("ccccc");request.setAdministrators(administrators);//管理员用户ID数组try {CreateLiveMessageGroupResponse response = client.getAcsResponse(request);return response.getGroupId();} catch (ClientException error) {throw new RuntimeException("创建消息组异常!" + error);}}/*** 查询指定用户下消息组列表** @param appId 互动消息应用ID*/public static Object listMessageGroup(String appId) throws Exception {IAcsClient client = createClient();ListLiveMessageGroupsRequest request = new ListLiveMessageGroupsRequest();request.setAppId(appId);request.setSortType(2);try {return client.getAcsResponse(request);} catch (ClientException error) {throw new RuntimeException("查询指定用户下消息组列表异常!" + error);}}/*** 消息组详情** @param parameter 请求参数*/public static Object groupDescribe(HashMap<String, String> parameter) throws Exception {IAcsClient client = createClient();DescribeLiveMessageGroupRequest request = new DescribeLiveMessageGroupRequest();request.setAppId(parameter.get("appId"));request.setGroupId(parameter.get("groupId"));try {return client.getAcsResponse(request);} catch (ClientException error) {throw new RuntimeException("查询指定用户下消息组列表异常!" + error);}}/*** 发送消息到群组** @param parameter 请求参数*/public static Object sendMessageGroup(HashMap<String, String> parameter) throws Exception {IAcsClient client = createClient();SendLiveMessageGroupRequest request = new SendLiveMessageGroupRequest();request.setAppId(parameter.get("appId"));request.setGroupId(parameter.get("groupId"));request.setSenderId(parameter.get("senderId"));//发送者request.setBody(parameter.get("body"));//消息内容request.setMsgType(Long.parseLong(parameter.get("msgType")));//消息类型try {return client.getAcsResponse(request);} catch (ClientException error) {throw new RuntimeException("发送消息到群组异常!" + error);}}/*** 发送消息到用户** @param parameter 请求参数*/public static Object sendMessageUser(HashMap<String, String> parameter) throws Exception {IAcsClient client = createClient();SendLiveMessageUserRequest request = new SendLiveMessageUserRequest();request.setAppId(parameter.get("appId"));request.setSenderId(parameter.get("senderId"));//发送者request.setReceiverId(parameter.get("receiverId"));//接收者request.setBody(parameter.get("body"));//消息内容try {return client.getAcsResponse(request);} catch (ClientException error) {throw new RuntimeException("发送消息到用户异常!" + error);}}/*** 查询群组消息列表** @param parameter 请求参数*/public static Object getGroupMessages(HashMap<String, String> parameter) throws Exception {IAcsClient client = createClient();ListLiveMessageGroupMessagesRequest request = new ListLiveMessageGroupMessagesRequest();request.setAppId(parameter.get("appId"));request.setGroupId(parameter.get("groupId"));request.setSortType(2);request.setPageSize(10);try {return client.getAcsResponse(request);} catch (ClientException error) {throw new RuntimeException("查询群组消息列表异常!" + error);}}/*** 查询群组用户列表** @param parameter 必须参数*/public static Object getGroupUsers(HashMap<String, String> parameter) throws Exception {IAcsClient client = createClient();ListLiveMessageGroupUsersRequest request = new ListLiveMessageGroupUsersRequest();request.setAppId(parameter.get("appId"));request.setGroupId(parameter.get("groupId"));request.setSortType(2);request.setPageSize(30);try {return client.getAcsResponse(request);} catch (ClientException error) {throw new RuntimeException("查询群组用户列表异常!" + error);}}
}

在这里插入图片描述
4、推流、断流回调

	/*** 推流、断流回调地址*/@GetMapping("/callback")public void callback(HttpServletRequest request) {try {//处理回调请求参数HashMap<String, Object> paramsMap = ConvertUtils.getRequestData(request);//开始推流if (paramsMap.get("action").equals("publish")) {tiktokLogger.info("开始推流:" + paramsMap);liveRoomsLogService.addRoomLog(paramsMap);}//推流中断if (paramsMap.get("action").equals("publish_done")) {tiktokLogger.info("推流中断:" + paramsMap);liveRoomsLogService.upRoomLog(paramsMap);}} catch (Exception e) {tiktokLogger.info("回调异常:" + e.getMessage());}}/*** 处理请求参数** @param request 请求* @return 结果*/public static HashMap<String, Object> getRequestData(HttpServletRequest request) {HashMap<String, Object> paramsMap = new HashMap<>(); //重新定义请求的参数Map<String, String[]> map = request.getParameterMap(); //请求中的map数组for (String key : map.keySet()) { //遍历数组String[] value = map.get(key);if (value.length == 1) {paramsMap.put(key, map.get(key)[0]);} else {paramsMap.put(key, value);}}return paramsMap;}

推流、断流日志

09:44:32.770 [http-nio-8082-exec-13] INFO  extend-tiktok - [callback,44] - 开始推流:{app=zyt.***.com, node=117.49.93.167, appname=TtSCpj, width=1080, action=publish, id=D6v3Su5mMQ, time=1723599872, usrargs=vhost=zyb.***.com&auth_key=1723603295-0-0-487e7adb13e00bdda7e7c6cbd97f88f8&ali_publisher&ali_edge_node_ip=117.49.93.167&ali_node_via=live13.cn4435%2clive15.l2et135-3&ali_node_ip=10.120.24.162#26%2c118.178.204.227#6&alilive_streamidv2=live13.cn4435_2955_3699959155_1723599872186&alilive_clienthost=live15.l2et135-3&orig_tc_url=rtmp://zyt.***.com/TtSCpj, height=1920}
09:46:06.204 [http-nio-8082-exec-15] INFO  extend-tiktok - [callback,50] - 推流中断:{app=zyt.***.com, node=117.49.93.167, appname=TtSCpj, width=1080, action=publish_done, id=D6v3Su5mMQ, time=1723599966, usrargs=vhost=zyb.***.com&auth_key=1723603295-0-0-487e7adb13e00bdda7e7c6cbd97f88f8&ali_publisher_ip=&ali_edge_node_ip=117.49.93.167&ali_node_via=live13.cn4435%2clive15.l2et135-3&ali_node_ip=10.120.24.162#26%2c118.178.204.227#6&alilive_streamidv2=live13.cn4435_2955_3699959155_1723599872186&alilive_clienthost=live15.l2et135-3&orig_tc_url=rtmp://zyt.***.com/TtSCpj, height=1920}
09:46:25.407 [http-nio-8082-exec-64] INFO  extend-tiktok - [callback,44] - 开始推流:{app=zyt.***.com, node=117.49.93.167, appname=Srvv66, ip=, width=1080, action=publish, id=b974e1hqmy, time=1723599985, usrargs=vhost=zyb.***.com&auth_key=1723603558-0-0-c54c7bad6bde755300bac0efb5ae44b7&ali_publisher_ip=&ali_edge_node_ip=117.49.93.167&ali_node_via=live6.cn4435%2clive3.l2et135-3&ali_node_ip=10.120.24.217#26%2c118.178.204.215#6&alilive_streamidv2=live6.cn4435_3485_3698551537_1723599984805&alilive_clienthost=live3.l2et135-3&orig_tc_url=rtmp://zyt.***.com/Srvv66, height=1920}
09:53:58.001 [http-nio-8082-exec-53] INFO  extend-tiktok - [callback,50] - 推流中断:{app=zyt.***.com, node=117.49.93.167, appname=Srvv66, ip=, width=1080, action=publish_done, id=b974e1hqmy, time=1723600437, usrargs=vhost=zyb.***.com&auth_key=1723603558-0-0-c54c7bad6bde755300bac0efb5ae44b7&ali_publisher_ip=&ali_edge_node_ip=117.49.93.167&ali_node_via=live6.cn4435%2clive3.l2et135-3&ali_node_ip=10.120.24.217#26%2c118.178.204.215#6&alilive_streamidv2=live6.cn4435_3485_3698551537_1723599984805&alilive_clienthost=live3.l2et135-3&orig_tc_url=rtmp://zyt.***.com/Srvv66, height=1920}
11:01:52.914 [http-nio-8082-exec-18] INFO  extend-tiktok - [callback,44] - 开始推流:{app=zyt.***.com, node=58.222.29.233, appname=Srvv66, ip=, width=1080, action=publish, id=b974e1hqmy, time=1723604512, usrargs=vhost=zyb.***.com&auth_key=1723603558-0-0-c54c7bad6bde755300bac0efb5ae44b7&ali_publisher_ip=&ali_edge_node_ip=58.222.29.233&ali_node_via=live1.cn3421%2clive15.l2et135-3&ali_node_ip=10.120.25.6#26%2c118.178.204.227#6&alilive_streamidv2=live1.cn3421_76677_2481419939_1723604511502&alilive_clienthost=live15.l2et135-3&orig_tc_url=rtmp://zyt.***.com/Srvv66, height=1920}
11:14:48.320 [http-nio-8082-exec-65] INFO  extend-tiktok - [callback,50] - 推流中断:{app=zyt.***.com, node=58.222.29.233, appname=Srvv66, ip=, width=1080, action=publish_done, id=b974e1hqmy, time=1723605288, usrargs=vhost=zyb.***.com&auth_key=1723603558-0-0-c54c7bad6bde755300bac0efb5ae44b7&ali_publisher_ip=&ali_edge_node_ip=58.222.29.233&ali_node_via=live1.cn3421%2clive15.l2et135-3&ali_node_ip=10.120.25.6#26%2c118.178.204.227#6&alilive_streamidv2=live1.cn3421_76677_2481419939_1723604511502&alilive_clienthost=live15.l2et135-3&orig_tc_url=rtmp://zyt.***.com/Srvv66, height=1920}

直播记录
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/400965.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

haproxy七层代理总结

一、HAProxy概念 1.1 什么是HAProxy&#xff1f; HAProxy是一款开源、高性能的负载均衡器和代理服务器&#xff0c;专为TCP和HTTP应用而设计。它可以将客户端的请求分发到多台后端服务器&#xff0c;从而提高应用的可用性和性能。HAProxy支持多种负载均衡算法和健康检查机制&a…

Python 3 入门基础知识【3】递归函数以及参数部分

在编码过程中除了使用Python内置的函数以外&#xff0c;我们也经常需要自己定义函数。今天来回顾python中的函数。 目录 1.定义函数 2.中函数的返回值 3.递归函数 4.Python函数参数 5.Python函数使用默认参数 6.Python函数使用可变参数 7.Python函数使用可变关键字参数 …

针对thinkphp站点的漏洞挖掘和经验分享

0x1 前言 浅谈 目前在学习和研究thinkphp相关漏洞的打法&#xff0c;然后最近对于thinkphp资产的收集方面有了一个简单的认识&#xff0c;然后写一篇新手看的thinkphp相关的漏洞收集和挖掘的文章来分享下。然后后面是给师傅们分享下后台文件上传&#xff0c;然后直接打一个ge…

WPF 资源、引用命名空间格式、FrameworkElement、Binding、数据绑定

资源 对象级别独立文件 静态资源使用(StaticResource)指的是在程序载入内存时对资源的一次性使用&#xff0c;之后就不再去访问这个资源了。 动态资源使用&#xff08;DynamicResource&#xff09;使用指的是在程序运行过程中仍然会去访问资源。 显然&#xff0c;如果你确定…

欧阳坚持每周一篇高质量文章,半年后收入1380.27元

前言 大家好&#xff0c;我是欧阳&#xff0c;到目前为止欧阳已经坚持连续高质量周更文章7个多月了。在第6个月时就想写一篇半年总结&#xff0c;但是因为拖延症直到现在才写这篇半年复盘文章。 我的成果 先来说一下连续周更半年取得的成果&#xff0c;分别是收入1380.27元、…

redis模块和ioredis的注意事项

redis模块和ioredis的注意事项 文章目录 redis模块和ioredis的注意事项前言一、ioredis和redis使用zrange的比较二、出现zrange结果不同的原因总结 前言 node.js在使用redis的时候有两个库可以选择&#xff0c;一个是redis、另一个是ioredis&#xff0c;我一直以来也没有太大关…

LeetCode之回溯

1.全排列 1.1 题目 1.2 题解 LeetCode 力扣官方题解 1.3 代码 class Solution {public List<List<Integer>> permute(int[] nums) {// 创建一个空的列表 res&#xff0c;用于存储所有的排列结果List<List<Integer>> res new ArrayList<>();/…

练习题PHP5.6+变长参数 ⇒ usort回调后门 ⇒ 任意代码执行

突破长度限制 使用usort上传后门 usort — 使用用户自定义的比较函数对数组中的值进行排序 paramusort(...$GET); ...为php设置可变长参数 在url地址栏中输入[]test&1[]phpinfo();&2assert 包含了phpiinfo&#xff08;&#xff09;命令执行 结合usort使用 assert…

SpringMVC快速入门

MVC模式 MVC&#xff08;Model-View-Controller&#xff09;模式是一种设计模式&#xff0c;用于分离应用程序的不同方面&#xff0c;以提高代码的组织性和可维护性。在Spring MVC框架中&#xff0c;MVC模式的作用是将应用程序的不同职责分开&#xff0c;从而简化开发和维护过…

Datawhale X 魔搭 AI夏令营第四期 AIGC方向 task02笔记

AI工具使用 1. baseline 代码2. 使用通义千问理解代码2.1 工作流程2.2 逐行释意 3. 使用通义千问生成 Prompt3.1 生成的 Prompt3.1 根据 Prompt 生成的图片 1. baseline 代码 !pip install simple-aesthetics-predictor!pip install -v -e data-juicer!pip uninstall pytorch-…

EasyBoss ERP上线TikTok热销数据功能,助力TikTok本土店卖家快速选品上货!

想要你的TikTok本土小店销量不断增长&#xff0c;选品至关重要。只有选品问题解决了&#xff0c;后续的投放、小店定调等动作才有意义。 因此&#xff0c;今天就来分享几种TikTok本土小店的选品策略。 一、TikTok Shop选品的底层逻辑 图源&#xff1a;TikTok Shop 在选品之前…

SpringBoot 自定义 starter

1. 官方文档 SpringBoot 版本 2.6.13&#xff0c;相关链接 Developing with Spring Boot 1.1 什么是 Starter Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop shop for all the Spring and relate…

C++哪些变量在没有显式初始化的情况下会被初始化为0

首先&#xff0c;我们需要明白C程序编译链接后会包含以下几个主要段(Section)。 代码段(.text)&#xff1a;存放程序的可执行代码&#xff0c;通常是只读的数据段(.data)&#xff1a;存放已初始化的全局变量和静态变量BSS段(.bss)&#xff1a;存放未初始化的全局变量和静态变量…

Git文件管理技巧:轻松删除与查看文件,忽略不必要的文件与文件夹!

避免文件混乱&#xff1a;Git 文件操作技巧 一、Git工作原理概述二、删除文件三、查看指定文件的修改四、指定不需要 Git 管理的文件五、总结 一、Git工作原理概述 Git是一种分布式版本控制系统&#xff0c;其核心在于其高效的快照机制、强大的分支与合并功能、本地开发的灵活…

详细分析JWT的基本知识(附Demo)

目录 前言1. 基本知识2. JWT验证过程3. Demo 前言 对于Java的基本知识推荐阅读&#xff1a; java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&#xff09;【Java项目】实战CRUD的功能整理&#xff08;持续更新&#xff09; 1. 基本知识 紧凑的、U…

《Kotlin核心编程》2021版复习记录

目录 0 前言1 基础语法1.1 数据类型1.2 数组1.3 集合1.4 遍历数据和集合1.5 函数声明返回值类型1.6 var 和 val 2 高阶函数和lambda表达式2.1 高阶函数2.2 方法和成员引用2.3 链式调用2.4 扩展函数2.5 面向表达式编程2.5.1 when表达式2.5.2 for循环2.5.3 in 2.6 字符串相等 3 面…

手撕初阶数据结构之---排序

1.排序概念及运用 排序&#xff1a;所谓排序&#xff0c;就是使⼀串记录&#xff0c;按照其中的某个或某些关键字的⼤⼩&#xff0c;递增或递减的排列起来的操作。 常见的排序算法 直接插入排序的时间复杂度是O(N^2) 这个是最差的情况下&#xff0c;就是大的在前面&#xff…

被老韭菜阴阳了?未来一个人最核心的能力:守脑如玉——早读(逆天打工人爬取热门微信文章解读)

tomato 版本TO&#xff1f; 引言Python 代码第一篇 洞见 未来一个人最核心的能力&#xff1a;守脑如玉第二篇 股友见闻结尾 &#xff08;你看出本质了吗&#xff1f;&#xff09; 引言 昨晚听别人的分析 好神奇 我会惊叹 为什么大家看到的都是同样的东西 而别人进行思考 思考…

Python 在PDF中添加条形码、二维码

在PDF中添加条码是一个常见需求&#xff0c;特别是在需要自动化处理、跟踪或检索PDF文件时。作为一种机器可读的标识符&#xff0c;PDF中的条码可以包含各种类型的信息&#xff0c;如文档的唯一标识、版本号、日期等。以下是一篇关于如何使用Python在PDF中添加条形码或二维码的…

Python开源项目周排行 2024年第13周

#2024年第13周2024年8月5日1roop一款基于深度学习框架TensorFlow和Keras开发的单图换脸工具包&#xff0c;提供了丰富的功能和简洁易用的界面&#xff0c;使得用户可以轻松实现单图换脸操作。支持多张人脸替换成同一个人脸&#xff0c;勾选多人脸模式即可 人脸替换 高清修复自…