首页
关于
壁纸
直播
留言
友链
统计
Search
1
《三国志英杰传》攻略
6,216 阅读
2
Emby客户端IOS破解
6,071 阅读
3
白嫖Emby
6,058 阅读
4
《吞食天地1》金手指代码
5,778 阅读
5
破解emby-server
4,317 阅读
moonjerx
game
age-of-empires
zx3
san-guo-zhi
尼尔:机械纪元
net
emby
learn-video
docker
torrent
photoshop
route
minio
git
ffmpeg
im
vue
gitlab
typecho
svn
alipay
nasm
srs
mail-server
tailscale
kkfileview
aria2
webdav
synology
redis
oray
chemical
mxsite
math
π
x-ui
digital-currency
server
nginx
baota
k8s
http
cloud
linux
shell
database
vpn
esxi
rancher
domain
k3s
ewomail
os
android
windows
ios
app-store
macos
develop
java
javascript
uniapp
nodejs
hbuildx
maven
android-studio
jetbrain
jenkins
css
mybatis
php
python
hardware
hard-disk
pc
RAM
software
pt
calibre
notion
office
language
literature
philosophy
travel
登录
Search
标签搜索
ubuntu
mysql
openwrt
zerotier
springboot
centos
openvpn
jdk
吞食天地2
synology
spring
idea
windows11
吞食天地1
transmission
google-play
Japanese
xcode
群晖
kiftd
MoonjerX
累计撰写
379
篇文章
累计收到
465
条评论
首页
栏目
moonjerx
game
age-of-empires
zx3
san-guo-zhi
尼尔:机械纪元
net
emby
learn-video
docker
torrent
photoshop
route
minio
git
ffmpeg
im
vue
gitlab
typecho
svn
alipay
nasm
srs
mail-server
tailscale
kkfileview
aria2
webdav
synology
redis
oray
chemical
mxsite
math
π
x-ui
digital-currency
server
nginx
baota
k8s
http
cloud
linux
shell
database
vpn
esxi
rancher
domain
k3s
ewomail
os
android
windows
ios
app-store
macos
develop
java
javascript
uniapp
nodejs
hbuildx
maven
android-studio
jetbrain
jenkins
css
mybatis
php
python
hardware
hard-disk
pc
RAM
software
pt
calibre
notion
office
language
literature
philosophy
travel
页面
关于
壁纸
直播
留言
友链
统计
搜索到
107
篇与
net
的结果
2022-12-05
win10访问webdav开启同时支持http和https
原因微软的操作系统 win7 和 win10 对 webdav 默认只支持 https 协议解决方案1.打开注册表快捷键 Win + R 输入 regedit 敲回车打开注册表2.修改BasicAuthLevel值在文件路径栏定位 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters 修改 BasicAuthLevel 值 1 改成 2 3.重启webclientnet stop webclientnet start webclient
2022年12月05日
298 阅读
0 评论
0 点赞
2022-11-21
自定义js组件$Message(一)
message.vue页面代码<template> <div class="msg-comp" :class="optionData.show ? 'slide' : ''" v-if="optionData.show"> <div class="msg-content" :style="{backgroundColor: optionData['bg-color']}"> <div class="msg-text" :style="{color: optionData['text-color']}">{{optionData.msg}}</div> </div> </div> </template> <script> export default { name: 'msg', props: { option: Object }, data () { return { countValue: 22, isShow: false, optionData: { 'show': false, // 是否展示 'time': 2000, 'bg-color': '#79dcb5', 'text-color': '#fff', 'msg': ''// 消息内容 } } }, watch: { option: { handler (newOption, oldOption) { if (newOption && typeof newOption === 'object') { this.optionData = Object.assign(this.optionData, newOption) } }, immediate: true, deep: true } }, methods: {}, mounted () { if (typeof this.option === 'object') { this.optionData = Object.assign(this.optionData, this.option) } this.optionData.show = true this.$nextTick(() => { setTimeout(() => { this.$destroy() document.body.removeChild(this.$el) }, this.optionData.time) }) } } </script> <style lang="less" scoped> .msg-comp { position: fixed; left: 50%; opacity: 0; transform: translate(-50%, -50%); z-index: 10000; &.slide { animation: slide 0.5s normal; animation-fill-mode: forwards } .msg-content { width: 200px; height: 50px; text-align: center; border-radius: 10px; .msg-text { line-height: 50px; } } } @keyframes slide { from { top: -10%; opacity: 0; } to { top: 15%; opacity: 1; } } </style>vue挂载脚本代码付费查看:传送门使用示例 mounted() { setInterval(()=>{this.$Message('弹窗提示')}, 3000) },
2022年11月21日
139 阅读
0 评论
0 点赞
2022-10-11
Docker 网络原理
Docker 网络原理容器是相对独立的环境,相当于一个小型的 Linux 系统,外界无法直接访问,那他是怎么做的呢,这里我们先了解下 Linux veth pair。1. Linux veth pairveth pair 是成对出现的一种虚拟网络设备接口,一端连着网络协议栈,一端彼此相连。如下图所示:veth pair将两个网络veth0和veth1连通。2. 理解Docker0我们先查看本地ip这里我们分析可得,有三个网络:lo 127.0.0.1 # 本机回环地址 eth0 172.31.179.120 # 阿里云的私有IP(如果你是虚拟机就是虚拟机的ip) docker0 172.17.0.1 # docker网桥lo和eth0在我们的虚拟机启动的时候就会创建,但是docker0在我们安装了docker的时候就会创建。docker0用来和虚拟机之间通信。问题:Docker 是如何处理容器网络访问的?我们先启动一个 tomcat 容器来说明。[root@jiangnan tomcat1]# docker pull tomcat [root@jiangnan tomcat1]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat latest fb5657adc892 2 months ago 680MB [root@jiangnan tomcat1]# docker run -d -p 8081:8080 --name tomcat01 tomcat 914a7d82b017f63f81c6eba49af5471441f1946c9d45509b69ab2c50c2713b6f [root@jiangnan tomcat1]#这里启动了tomcat01,我们再来查看网络发现:我们前面查看的时候还是三组网卡,当启动了一个tomcat容器之后,多了一组网卡201: vethad33778@if200,而且还是成对的。同样我们再来启动一个tomcat02会又多出一对网卡。进入了 tomcat01 容器内可以看到 tomcat01 对应的 ip 地址为:172.17.0.2在宿主机上也可ping通。说明:tomcat02对应的ip为172.17.0.3,也可以ping通。结论:我们每启动一个容器,就会多出一对网卡,同时他们被连接到docker0上,而docker0又和虚拟机之间连通。也可以通过inspect查看。[root@jiangnan tomcat1]# docker network ls NETWORK ID NAME DRIVER SCOPE 4d3e75606593 bridge bridge local # 这个就是docker0 8e92ee24e5f6 host host local e85ffb1f2cc3 none null local [root@jiangnan tomcat1]# docker inspect 4d3e75606593 "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" # 网关 } ] }, "Containers": { # 容器 "15910ee083965d60c46bf9b3b292570fef9b8925905aa4df90c6d48142bb2eee": { "Name": "tomcat01", "EndpointID": "9c7a5ab65f1fc91b1d92ad61dec9b2f518f67f69f662522483dca789616f42aa", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" }, "6c9a6a5d8eca9ad52926008c7b30516d23293ff8ad1f38947957d571431d5297": { "Name": "tomcat02", "EndpointID": "f83c1e643236cd65f50fba03929ca14d5df8d135b1f6cb8adf203cf96084f7aa", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" } },我们可以抽象为这样一个网络模型。在这里,我们可以看到Docker0相当于一个路由器的作用,任何一个容器启动默认都是docker0网络。另外,搜索公众号GitHub猿后台回复“赚钱”,获取一份惊喜礼包。docker默认会给容器分配一个可用ip,并把它同docke0相连。使用到的就是veth pair技术。3. 容器互联–Link在网络模型图中可以看出,容器和容器之间不能直接连通。前面我们启动的两个 tomcat 对应的 hosts 如下:[root@jiangnan tomcat1]# docker exec -it tomcat01 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 3ecb3204e2dc root@3ecb3204e2dc:/usr/local/tomcat#[root@jiangnan tomcat1]# docker exec -it tomcat02 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 6c9a6a5d8eca [root@jiangnan tomcat1]#发现:他们的 hosts 中只有各自的ip地址。但是在实际的工作中,容器使用的是虚拟ip,每次启动ip都会变化,思考一个场景,我们编写一个微服务,数据库连接地址原来是使用ip的,如果ip变化就不行了,那我们能不能使用服务名访问呢?我们在启动一个tomcat03,使用—link绑定到tomcat02上。然后看它的hosts是什么样的。[root@jiangnan tomcat1]# docker run -d -p 8083:8080 --name tomcat03 --link tomcat02 tomcat db75c42f7f7f609218deb290d3e923e3c7da6bcf8c0b38cde27962fb2b9e9a54 [root@jiangnan tomcat1]# docker exec -it tomcat03 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 tomcat02 e4060ea4ee28 # 发现tomcat2直接被写在这里 172.17.0.4 db75c42f7f7f root@db75c42f7f7f:/usr/local/tomcat#发现:使用了–link,不但有了自己的ip,而且还有了tomcat02的服务名。但是tomcat02中并没有tomcat03的,因为–link是单向的。这样就实现了容器和容器之间的连通。不需要通过ip地址连通,而是通过服务名就可以。但是使用—link的方法过时了,我们一般使用自定义网络。4.自定义网络(推荐)docker0的特点:它是默认的域名访问不通–link 域名通了,但是删了又不行docker为我们提供了三种网络模式[root@jiangnan tomcat1]# docker network ls NETWORK ID NAME DRIVER SCOPE 4d3e75606593 bridge bridge local 8e92ee24e5f6 host host local e85ffb1f2cc3 none null local [root@jiangnan tomcat1]#这其中默认使用的是 bridge,也就是我们的docker0网卡。在我们启动容器的时候,实际上是如下命令[root@jiangnan tomcat1]# docker run -d -P --name tomcat01 --net bridge tomcat这个—net是默认的,所以被省略了。下面我们自定义一个网络 mynet。# 自定义创建的默认default "bridge" [root@jiangnan tomcat1]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet 3136d64109c6f285bc69d3ee4be901524292d0e5ddd9e414d49197dfa6c19ba1 [root@jiangnan tomcat1]# docker network ls NETWORK ID NAME DRIVER SCOPE 4d3e75606593 bridge bridge local 8e92ee24e5f6 host host local 3136d64109c6 mynet bridge local # 多了一个mynet e85ffb1f2cc3 none null local [root@jiangnan tomcat1]# docker network inspect mynet [ { "Name": "mynet", "Id": "3136d64109c6f285bc69d3ee4be901524292d0e5ddd9e414d49197dfa6c19ba1", "Created": "2022-02-27T14:15:44.676693958+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16", # 子网地址 "Gateway": "192.168.0.1" # 网关 } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ] [root@jiangnan tomcat1]#下面我们使用自定义的网络启动 tomcat[root@jiangnan tomcat1]# docker run -d -p 8081:8080 --name tomcat-net-01 --net mynet tomcat 675439c851dc29355c03f82bb163f9e5a326e230447d86d40d53ff08766cfd06 [root@jiangnan tomcat1]# docker run -d -p 8082:8080 --name tomcat-net-02 --net mynet tomcat 31f12c9332e8b4b6e66619dc988533f2863b80e71dbf490c8313694637814ca1 [root@jiangnan tomcat1]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 31f12c9332e8 tomcat "catalina.sh run" 3 seconds ago Up 2 seconds 0.0.0.0:8082->8080/tcp, :::8082->8080/tcp tomcat-net-02 675439c851dc tomcat "catalina.sh run" 12 seconds ago Up 12 seconds 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp tomcat-net-01 [root@jiangnan tomcat1]#查看网络[root@jiangnan tomcat1]# docker inspect mynet [ { "Name": "mynet", "Id": "3136d64109c6f285bc69d3ee4be901524292d0e5ddd9e414d49197dfa6c19ba1", "Created": "2022-02-27T14:15:44.676693958+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16", "Gateway": "192.168.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "31f12c9332e8b4b6e66619dc988533f2863b80e71dbf490c8313694637814ca1": { "Name": "tomcat-net-02", "EndpointID": "1c0e9dbffff295f2326bfd1e2847c0f1d9136ff00519101bb11d922e7da4f818", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" }, "675439c851dc29355c03f82bb163f9e5a326e230447d86d40d53ff08766cfd06": { "Name": "tomcat-net-01", "EndpointID": "2653da0a25d166f0d7222235e85d8231d9424e19949b6e6b7cfa1a3eddcc462b", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] [root@jiangnan tomcat1]## 我们来测试ping容器名和ip试试,都可以ping通 [root@jiangnan ~]# docker exec -it tomcat-net-01 ping 192.168.0.3 PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data. 64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.093 ms [root@jiangnan ~]# docker exec -it tomcat-net-01 ping tomcat-net-02 PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data. 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.063 ms 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.066 ms发现:不用—link也可以直接通过服务名ping通了。5.网络连通docker0和自定义网络肯定不通,我们使用自定义网络的好处就是网络隔离。但是在实际的工作中,比如我们部署了mysql使用了一个网段。部署了tomcat使用了另一个网段,两个网段之间肯定是不能相互连通的,但是tomcat和mysql又需要相互连通,我们就要使用网络连通。原理图如下:网络连通就是将一个容器和一个网段之间的连通。比如我前面使用的默认docker0的tomcat01,需要连接到mynet网络。# docker network connect 网络 容器 [root@jiangnan tomcat1]# docker network connect mynet tomcat01 [root@jiangnan tomcat1]# docker network inspect mynet [ { "Name": "mynet", "Id": "3136d64109c6f285bc69d3ee4be901524292d0e5ddd9e414d49197dfa6c19ba1", "Created": "2022-02-27T14:15:44.676693958+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16", "Gateway": "192.168.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "2e709013935463c29caf28771bb49925fee4e02842459b339d7dd1ad5dedf9b7": { "Name": "tomcat-net-01", "EndpointID": "9f3a46bad37ade7935e283715caa5699e9a7e22175b592f4a4792a37c351d969", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" }, "5c0c544f2507d9f5f456feceddbd853ebccc07cea8c39c8479693731e480bf55": { "Name": "tomcat01", "EndpointID": "d05abb2d31af4067c5a45f299ce7b4401b1fa81638a44b6c09f3de7f8f4221fe", "MacAddress": "02:42:c0:a8:00:04", "IPv4Address": "192.168.0.4/16", "IPv6Address": "" }, "d6066db5fdd0b508514107a896ed20b639eaa47dbd97a025ad0c52250766c8a4": { "Name": "tomcat-net-02", "EndpointID": "3a5f6f2a07d900303382b290825c9f52640689c859608c741c7c7d81031e107e", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] [root@jiangnan tomcat1]#通过这种方式直接将tomcat01加到了mynet网络中。6.总结veth pair是成对出现的一种虚拟网络设备接口,一端连着网络协议栈,一端彼此相连。docker中默认使用docker0网络。docker0相当于一个路由器的作用,任何一个容器启动默认都是docker0网络。docker0是容器和虚拟机之间通信的桥梁。推荐使用自定义网络,更好实现使用服务名的连通方式,避免ip改变的尴尬。网络之间不能直接连通,网络连通是将一个容器和一个网络之间的连通,实现跨网络操作。
2022年10月11日
103 阅读
0 评论
0 点赞
2022-09-22
uniapp使用computed和store遇坑
1.用户登录后存储用户信息到 uni.setStorageSync(userInfo) 2.在 vuex 中 state 中写方法 state: { userInfo: () => Storage.getUserInfo() }, getters: { getUserInfo(state) { return state.userInfo() }, }, mutations: { setUserInfo(state, data) { state.userInfo = () => data }, }, actions: { setUserInfo(context, data) { context.commit('setUserInfo', data) } }试探过的无效方法:getters: { getUserInfo(state) { return Storage.getUserInfo() } },3.个人中心页面 user-center.vue 是 tabbar.vue 的子组件页面,在 user-center.vue 中的 computed 中直接使用 this.$Storage.getUserInfo() 方法 无法及时获取数据更新 遂不得已而采用vuex机制来保证页面数据及时更新computed: { syncUserInfo: function() { return this.$store.getters.getUserInfo || {} } },以上方法,只更新 Storage.getUserInfo() 数据,state变量是不会同步渲染更新的,必须调用this.$store.commit('setUserInfo', userInfo)来更新用户信息后才会全局更新4.vuex是非持久化数据,所以(1)通过 uni.setStorageSync(userInfo) 来做数据持久化(2)通过vuex机制来做数据的全局同步更新(3)两者结合实现App全局变量数据更新5.解决了以下几个问题(1)诸如用户信息、用户财务信息等App全局变量的数据一致性(2)避免了在不同页面频繁请求同一接口获取用户信息(3)在用户登录时获取用户信息后提前渲染用户信息页面,增强用户前端体验
2022年09月22日
276 阅读
0 评论
0 点赞
2022-07-17
破解emby-server
前言现在很多服务的正常运行都依赖某个中心服务器,如果服务器升级或出现故障或者公司跑路,付费用户将无法继续正常使用。emby也是如此,程序要访问mb3admin.com确认你是付费用户才能使用更多的功能,不管你的个人网络还是他们服务器出问题,都将不能使用付费功能。网络上有一些解决方案,但大都需要搭建一个nginx伪装站点,生成ssl证书,emby服务器上添加证书并且修改hosts文件,客户端也需要修改hosts或者重定向mb3admin.com到伪站……我认为这样破解太过复杂了,用别人的伪站又担心不稳定。所以,就有了今天的尝试,修改emby程序,让其在不设置伪站的情况下也能使用最基本的是付费功能。破解过程需要用到下面两个工具:js-beautify dnSpy emby-server在Linux系统中安装于/opt/emby-server/,把此文件夹复制到hack-emby目录,并在此目录执行下面的脚本,美化javascript代码,以方便阅读。#!/bin/bash for f in $(find emby-server/ -name "*.js") do echo "$f" js-beautify "$f" > tmp mv tmp "$f" done在浏览器打开emby,在Emby Premiere页面随便输入一个key按保存后提示Emby Premiere key is missing or invalid.搜索定义并调用这个字符串的位置,发现仅在 system/dashboard-ui/embypremiere/embypremiere.html 中有调用这个字符串,同目录有个 embypremiere.js ,根据 MediaBrowser.Model.dll 中的某些函数返回值,执行相关的判断。修改 MediaBrowser.Model.dll 中的 get_IsMBSupporter 和 get_SupporterKey 的返回值后不再提示这个错误,不过也不像付费用户一样显示。还需要修改 emby-server/system/dashboard-ui/embypremiere/embypremiere.js 中的load(page)函数,去除访问 mb3admin.com 相关的代码,并且硬编码返回给付费用户的json数据才能正常显示。function load(page) { var apiClient; loading.show(), (apiClient = ApiClient).getJSON(apiClient.getUrl("Plugins/SecurityInfo")).then(function(info) { var key, postData; page.querySelector("#txtSupporterKey").value = info.SupporterKey || "", page.querySelector("#txtSupporterKey").classList.remove("invalidEntry"), page.querySelector(".notSupporter").classList.add("hide") var statusInfo = {"deviceStatus":"0","planType":"Lifetime","subscriptions":{}}; var statusLine, indicator = page.querySelector("#status-indicator .listItemIcon"), extendedPlans = page.querySelector("#extended-plans"); switch (extendedPlans.innerHTML = globalize.translate("MessagePremiereExtendedPlans", '<a is="emby-linkbutton" class="button-link" href="https://emby.media/premiere-ext.html" target="_blank">', "</a>"), statusInfo.deviceStatus) { default: statusLine = globalize.translate("MessagePremiereStatusGood", statusInfo.planType), indicator.classList.remove("expiredBackground"), indicator.classList.remove("nearExpiredBackground"), indicator.innerHTML = "", extendedPlans.classList.add("hide") } page.querySelector("#premiere-status").innerHTML = statusLine; var sub, subsElement = page.querySelector("#premiere-subs"); statusInfo.subscriptions && 0 < statusInfo.subscriptions.length ? (page.querySelector("#premiere-subs-content").innerHTML = (subs = statusInfo.subscriptions, key = info.SupporterKey, subs.map(function(item) { var itemHtml = "", makeLink = item.autoRenew && "Stripe" === item.store, tagName = makeLink ? "button" : "div"; return itemHtml += ("button" == tagName ? '<button type="button"' : "<div") + ' class="listItem listItem-button listItem-noborder' + (makeLink ? " lnkSubscription" : "") + '" data-feature="' + item.feature + '" data-key="' + key + '">', itemHtml += '<i class="listItemIcon md-icon">dvr</i>', itemHtml += '<div class="listItemBody two-line">', itemHtml += '<div class="listItemBodyText">', itemHtml += globalize.translate("ListItemPremiereSub", item.planType, item.expDate, item.store), itemHtml += "</div>", itemHtml += '<div class="listItemBodyText listItemBodyText-secondary">', itemHtml += globalize.translate("Stripe" === item.store ? item.autoRenew ? "LabelClickToCancel" : "LabelAlreadyCancelled" : "LabelCancelInfo", item.store), itemHtml += "</div>", itemHtml += "</div>", itemHtml += "</" + tagName + ">" })), (sub = page.querySelector(".lnkSubscription")) && sub.addEventListener("click", cancelSub), subsElement.classList.remove("hide")) : subsElement.classList.add("hide"), page.querySelector(".isSupporter").classList.remove("hide") //var subs, key }), loading.hide() }这里并不是最重要的,也许恰恰是最不重要的,因为我修改相关的代码后,Dashboard页面并没有显示徽章,不能使用付费主题,不能看live tv,右上角的升级会员按钮没有消失。这个程序以前是开源的,后来闭源后越来越不好破解了!(不过javascript和C#跟开源没啥区别)显示徽章Dashboard中徽章位于emby-server/system/dashboard-ui/css/images/supporter/supporterbadge.png,脚本system/dashboard-ui/dashboard/dashboard.js中的renderSupporterIcon函数使用了这个图标,调用这个函数的代码段为:function() { var apiClient = window.ApiClient; return apiClient ? connectionManager.getRegistrationInfo("themes", apiClient, { viewOnly: !0 }).then(function(result) { return { IsMBSupporter: !0 } }, function() { return { IsMBSupporter: !1 } }) : Promise.reject() }().then(function(pluginSecurityInfo) { DashboardPage.renderSupporterIcon(page, pluginSecurityInfo); var html, supporterPromotionElem = page.querySelector(".supporterPromotion"), isSupporter = pluginSecurityInfo.IsMBSupporter;只要把IsMBSupporter: !1改为 IsMBSupporter: !0 就可以显示徽章了。修改 emby-server/system/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js 的getRegistrationInfo应该会更好,因为多处代码都调用了这个函数!key: "getRegistrationInfo", value: function(feature, apiClient, options) { var params = { serverId: apiClient.serverId(), deviceId: this.deviceId(), deviceName: this.deviceName(), appName: this.appName(), appVersion: this.appVersion(), embyUserName: "" }; (options = options || {}).viewOnly && (params.viewOnly = options.viewOnly); var cacheKey = getCacheKey(feature, apiClient, options), regInfo = JSON.parse(this.appStorage.getItem(cacheKey) || "{}"), timeSinceLastValidation = Date.now() - (regInfo.lastValidDate || 0); if (timeSinceLastValidation <= 864e5) return console.log("getRegistrationInfo returning cached info"), Promise.resolve(); var regCacheValid = timeSinceLastValidation <= 864e5 * (regInfo.cacheExpirationDays || 7); params.embyUserName = apiClient.getCurrentUserName(); var currentUserId = apiClient.getCurrentUserId(); if (currentUserId && "81f53802ea0247ad80618f55d9b4ec3c" === currentUserId.toLowerCase() && "21585256623b4beeb26d5d3b09dec0ac" === params.serverId.toLowerCase()) return Promise.reject(); var appStorage = this.appStorage, getRegPromise = ajax({ url: "https://mb3admin.com/admin/service/registration/validateDevice?" + paramsToString(params), type: "POST", dataType: "json" }).then(function(response) { return appStorage.setItem(cacheKey, JSON.stringify({ lastValidDate: Date.now(), deviceId: params.deviceId, cacheExpirationDays: response.cacheExpirationDays })), Promise.resolve() }, function(response) { var status = (response || {}).status; return console.log("getRegistrationInfo response: " + status), 403 === status ? Promise.reject("overlimit") : status && status < 500 ? Promise.reject() : function(err) { if (console.log("getRegistrationInfo failed: " + err), regCacheValid) return console.log("getRegistrationInfo returning cached info"), Promise.resolve(); throw err }(response) }); return regCacheValid ? (console.log("getRegistrationInfo returning cached info"), Promise.resolve()) : getRegPromise }把 if (timeSinceLastValidation <= 864e5) return console.log("getRegistrationInfo returning cached info"), Promise.resolve(); 中的 timeSinceLastValidation <= 864e5 替换为true,确保始终返回本地缓存中的数据,而不再需要找服务器验证。不过程序可能为了防止这个js文件被修改,在 emby-server/system/dashboard-ui/app.js 中有这么一段代码: define("connectionManagerFactory", [], getDynamicImport("./bower_components/emby-apiclient/connectionmanager.js"))运行时从emby-server/system/Emby.Web.dll中动态导入这个js文件,而不是使用 emby-server/system/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js ,使用dnSpy的Hex Editor修改这几个字节就可以了。破解会员功能上面两个并没那么重要,上传、下载、电视直播和dvr这类功能才是更加实用的,这些都跟validateFeature有关系。同样,这个函数不仅存在于system/dashboard-ui/modules/registrationservices/registrationservices.js,在Emby.Web.dll中也有备份,我们要修改后者才能生效。{ validateFeature: function(feature, options) { return options = options || {}, console.log("validateFeature: " + feature), iapManager.isUnlockedByDefault(feature, options).then(function() { return showPeriodicMessageIfNeeded(feature) }, function() { var unlockableFeatureCacheKey = "featurepurchased-" + feature; if ("1" === appSettings.get(unlockableFeatureCacheKey)) return showPeriodicMessageIfNeeded(feature); var unlockableProduct = iapManager.getProductInfo(feature); if (unlockableProduct) { var unlockableCacheKey = "productpurchased-" + unlockableProduct.id; if (unlockableProduct.owned) return appSettings.set(unlockableFeatureCacheKey, "1"), appSettings.set(unlockableCacheKey, "1"), showPeriodicMessageIfNeeded(feature); if ("1" === appSettings.get(unlockableCacheKey)) return showPeriodicMessageIfNeeded(feature) } var unlockableProductInfo = unlockableProduct ? { enableAppUnlock: !0, id: unlockableProduct.id, price: unlockableProduct.price, feature: feature } : null; return iapManager.getSubscriptionOptions().then(function(subscriptionOptions) { if (0 < subscriptionOptions.filter(function(p) { return p.owned }).length) return Promise.resolve(); var registrationOptions = { viewOnly: options.viewOnly }; return connectionManager.getRegistrationInfo(iapManager.getAdminFeatureName(feature), connectionManager.currentApiClient(), registrationOptions).catch(function(errorResult) { return !1 === options.showDialog ? Promise.reject() : ("overlimit" === errorResult && (alertPromise = alertText("Your Emby Premiere device limit has been exceeded. Please check with the owner of your Emby Server and have them contact Emby support at support@emby.media if necessary.").catch(function() { return Promise.resolve() })), (alertPromise = alertPromise || Promise.resolve()).then(function() { var dialogOptions = { title: globalize.translate("HeaderUnlockFeature"), feature: feature }; return currentValidatingFeature = feature, showInAppPurchaseInfo(subscriptionOptions, unlockableProductInfo, dialogOptions) })); var alertPromise }) }) }) }, showPremiereInfo: showPremiereInfo }修改这个函数的返回值,并保存。替换掉系统中相关的文件,刷新浏览器缓存,就可以使用会员的大部分功能了。上图是破解前,即使正版程序,在局域网无法访问mb3admin.com时,可能也无法使用付费功能。下图为破解后,emby-server不再访问mb3admin.com而是直接返回缓存中/硬编码在dll和js中的数据。致敬作者:转载自https://bbs.pediy.com/thread-263534.htm
2022年07月17日
4,317 阅读
1 评论
0 点赞
1
...
7
8
9
...
22
您的IP: