Protogalaxy

Planet #0

PHSS-Core开发日志#11 阶段性总结与下一步的开发计划

经过了毕设答辩之后,PHSS-Core也终于是完成了一个阶段的开发工作,回到家的这几天时间里,由于项目的初期开发都是以实现毕设文档中所计划的功能为目标,所以项目的开发顺序被些许打乱,现如今答辩工作完成,一时间有点不知道下一步该写点什么来推进整个项目的开发进度,所以整个项目的开发陷入了停滞,因此在这里做一下简单的阶段性总结,整理一下目前的进度,规划一下接下来的工作。 经过了紧(lan)锣(lan)密(san)鼓(san)的几个月的开发,整个项目也走到了一个阶段性的节点,截至现在,完成的进度节点有以下几个: 数据库整体结构设计 基于Spring Data JPA的DO层 基于Spring Security的简单登录注册功能 基于FFmpeg与JavaCV的音频元数据获取 基于Metadata的音频自动分类存放 音频查询接口 目前各方面待完成的目标有: DO层: 进一步完善数据库设计,优化查询效率 将实体文件与数据库条目绑定,完成级联更新与删除功能 安全层: 解决React前端配合后台CSRF防御的问题 解决跨域访问问题 将鉴权体系向JSON Web Token平移 添加生物识别登录功能 服务: 进一步研究NIO的功能与特点,提高多文件传输的效率 文档管理 视频管理 电影管理 番组管理 接入弹弹Play API,提供番组查询,订阅,提示Continue readingPHSS-Core开发日志#11 阶段性总结与下一步的开发计划

Java-Music-Utilities开发日志#1 简单功能完成

在经过了初期阶段的开发过程后,终于是完成了基本的结构设计与简单的文字性音频元数据读取功能,在初期的结构设计中,Java-Music-Utilities预计有音频转码,音频元数据读写这两个功能。 目前主要有三个类:MusicContainer,Metadata,Converter,分别是音频文件的容器类,元数据获取与集合类,转码类。现在的工作方式是使用MusicContainer的构造器来初始化音频容器,提供Path与byte流两种初始化方式。然后选择将MusicContainer作为唯一参数传入Metadata或Converter的构造其中来初始化元数据容器或者是转码实例。 截止目前,我只实现了文字性元数据的获取,由于JavaCPP-Presents-FFmpeg正处于大版本的更迭期,封面获取的关键性函数的用法缺少文档,所以下一步的计划是在没有文档的情况下依靠简易的JavaDoc来专注完成音频封面的获取,然后再考虑转码类的编写问题,以上。

一个基于JavaCPP Presents-FFmpeg的轮子开发计划

在PHSS音频管理功能的开发过程中,由于涉及到了音频文件的一些处理工作,包括音频元数据的读取,转码等,处于对开发便捷性的需求,在开发的前期,我在Github上寻找了很长时间音频处理相关的Java库。但事与愿违,经过了一番查询,可能是由于Java在这方面的应用非常少,能找到的相关库都很老旧并且长时间没有更新,还有一些库只是单纯基于命令行版FFmpeg的命令行工具,有点难用,并且Java自带的音频处理接口也都很长时间没有更新,并且支持的音频格式非常少,所以我在不得以自己写工具类的同时,也萌生写一个正经的轮子的想法,因此发起了这个名为Java-Music-Utilities的项目,Github的地址在这里。

PHSS-Core开发日志#10 FFmpeg与其JavaCPP实现踩坑纪录

Ps.PHSS的这部分开发过程中还衍生出了一个基于FFmpeg的java原生音视频metadata获取的轮子,相关文章可以参考这里。 前言 在完成了简单的安全层架构,实现了基本的登录功能之后,项目中于是进入了较为核心的音视频管理功能的开发阶段,在前期技术选型时,考虑到项目的可维护性与稳定性,我最终选择了FFmpeg作为PHSS的多媒体管理外部库,作为老牌多媒体处理软件,FFmpeg的可用性与稳定性都是经过了多年生产环境检验的。 但是在编写专辑音轨管理功能的具体实现过程中,我发现FFmpeg这个东西竟然找不太到全面且易读的开发相关的Guide和Documentation。并且实际使用过程中所用到的FFmpeg的Java实现(FFmpeg-JavaCPP-Presents,基于JavaCPP,由Bytedeco编写)更是只有一个基本的demo,FFmpeg的其他更深度的内容也是一点都没提,在Google上能找到的也大多都是命令行版的FFmpeg的使用方法,在Github上能找到的音视频metadata获取相关的项目也大多都是基于命令行版FFmpeg或者是其他一些奇奇怪怪的,早已停止更新的第三方库,看起来非常的不靠谱。由于FFmpeg的Java实现是基于JavaCV的子项目,更新一直都非常稳定,所以我还是坚定不移的选择了JavaCPP版FFmpeg作为项目的多媒体处理库,因此我只能自己一点点看那个JavaDoc和网上能找到的一些零星的老版本的开发示例来一点点学习相关的开发知识,在这里记录以下,方便自己和其他有需要的老哥们日后有个参考。(以下叙述是以FFmpeg-JavaCPP作为基础,其基础技术JNI的相关介绍可以点这里)

PHSS-Core开发日志#9 Spring Security ACL配置#1

在完成了PHSS-Core对Spring Security的引入的初期阶段是之后,我又引入了Spring Data REST用来快速构建RESTful的资源访问与操纵API,在实现了Spring Data REST的基本功能之后,又有一个新的问题出现了–那就是REST API下资源的访问权限问题。 在只有Spring Security基础配置的情况下,用户登录后,通过RESTful api(/rest)可以访问到数据库中的所有资源,也就是说当某个登录后,调用/rest/musicAlbumEntities接口,不仅可以看见属于自己的专辑,还可以看见整个数据库中其他用户的专辑。经过对Spring Data REST的说明文档的一番研读,发现最接近我的要求的是@PreAuthorize功能,该注解提供了方法级的安全性控制,也就是说只有特定用户才能访问特定方法,但在经过尝试之后PreAuthorization模型并不能满足我的需求,所以我又将眼光转回到了Spring Security的说明文档上。

PHSS-Core开发日志#8 Spring Security踩坑指南

在完成了由Hibernate到Spring Data JPA的切换后,我开始了Service层的设计,由于PHSS对安全性以及开发速度的需求,我选择了使用同属Spring Projects系列的Spring Security。 安全是一个非常抽象且不断变化的概念,在如今的Web环境下,一个动态的,不断完善的安全系统显得至关重要。在现代Web应用中,只有建立一个完善的安全层才能尽可能保证各个层级的安全性。 在现在的网络环境中,常见的攻击手段有XSS,SQL注入,CSRF,SSRF,xee,xPath注入等。 我们要做的就是在安全层建立完备的系统来防御这些可以预见的以及其他不可预见的攻击。在系统底层,我们需要处理诸如传输安全与系统识别的问题,最简单的例子就是开启https连接使用X.509认证以防止传输过程中的中间人攻击。然后我们还需要将关键的数据-例如密码与身份证号等各种信息进行加密储存以最大程度的防止系统被攻破后的数据泄露。在Service层,我们需要一套完善的权限管理机制来确保数据只能被拥有相关权限的用户访问到,更加高级的还有方法级的授权验证等。

PHSS-Core开发日志#7 Spring Data JPA及Spring data REST配置记录

1.Spring Data JPA 随着开发进度的不断推进,由于对REST服务的需求与对开发速度的需要,加之在设计初期PHSS的整个系统就坚定拥抱了Spring Projects,所以在Service开发开始前的这个节点,我将ORM框架由基本的Hibernate切换到了与Spring的其他各种项目更有亲和性,并且开发更为简便的Spring Data系列,包括Spring data JPA,Spring data REST。

PHSS-Core开发日志#6 密码加密算法对比

在互联网发展的初期,密码大多是以明文存储的,因为密码被认为是安全的,它需要凭证才能够被访问到。但是,攻击者可以通过SQL注入等攻击方式来获取大量的密码。随着越来越多的密码被这些攻击手段所获取,安全领域的专家们开始意识到需要一中更加安全的方式来保护用户的密码。 随后,安全领域开始鼓励开发人员使用单向散列算法(也称Hash算法,例如SHA256)来将密码进行加密存储。当用户尝试认证时,系统将用户上传的密码hash后与数据库中储存的hash值进行比较,这意味着数据库只需存储密码的单向散列。如果系统被攻破,也只会暴露密码的单向散列,由于在计算上很难通过单向散列值来破解密码,因此这种方法在很大程度上提高了密码的安全性。但是随着黑客技术的发展,攻击者也开始使用彩虹表(Rainbow Tables)来辅助破解,攻击者并不是每次都是在猜测密码,而是通过彩虹表来使用“以空间换时间”的策略来进行密码破解。

PHSS-Core开发日志#5 Token的设计#1

由于PHSS的前后端分离特性,在设计PHSS的安全系统的时候了解到了JWT(JSON Web Token)策略,经过了一番权衡,处于对扩展性与易用性的需求,我决定使用JWT鉴权体系。由于JWT的特性,很多信息都将由Token来承载,所以Token的设计也成为了必须关注的一个点。以下关于JWT规约的内容译自jwt.io

PHSS-Core开发日志#4 再谈主键策略

在PHSS的设计初期,由于数据库设计经验·的不足以及对于数据库跨表ID唯一性的需求,在一番查询之后我选择了UUID作为整个系统的ID类型。但是在实际代码编写的过程中,由于采用了基于JPA的Hibernate Bootstrap方式,在fetching的时候需要使用JPA提供的基于EntityManager的·fetch方法,比如EntityManager.find()与EntityManager.createQuery()。但不尽如人意的是,在主键采用UUID类型的情况下,JPA所提供的Fetching方法出现了不可预知的问题:在UUID具体值已确定的条件下,使用entitymanager.find()方法通过UUID进行fetching,即使UUID正确,也会出现entity无法找到的问题,尝试两种fetching方式后都无法定位,并且Google和Stackoverflow查询未果后,最终还是决定更换主键策略。在更加深入地研究了各种主键策略之后,发现自己以前对数据库主键的理解还是存在一些问题,所以在这里重新总结一下关于数据库主键策略选择的各种要点。

PHSS-Core开发日志#3 预期功能与数据库架构

在开发初期,作为智能家庭服务器(Home server)PHSS在设想下应有以下功能(当然,只是设想。作为一个死宅程序员,其中还夹杂了点私货wwwww): 个人资料库管理:音乐专辑,视频,电影,动漫番组,电子书籍,插画,文档 个人日程与档案管理:日历,日程提醒,便利贴,番组信息,RSS订阅,新闻抓取 本地Git管理 Google Home与Apple Homekit功能接入,包括家庭用电量统计,智能家电自动控制与场景切换 安全性方面,在支持密码登录的基础上,加入生物信息登录与物理key登录 经过简单的初期设计,半成品数据库结构大致如下: 考虑到Google Home与Apple Homekit接入的复杂性,所以暂时搁置,目前只是大致设计出了个人资料库与个人日程档案的大致数据库结构。由于资料库系统在预期情况下可能发生大量文件读取,所以将文件系统的数据库结构做了一些范式化设计。

PHSS-Core开发日志#1 后台技术选型

1.Maven还是Gradle? Maven的优点:Maven配置文件的繁琐有时会反而成为它的优点,Gradle虽灵活,但在大型项目中,Maven的配置方式所带来的稳定性目前仍不是Gradle所可比拟的。 Maven的缺点:当项目体积开始膨胀时会导致XML形式的配置文件阅读体验较差,维护起来比较麻烦。Build一次耗时较Gradle慢很多。 Gradle的优点:Gradle的官网提供了非常详细的与Maven的对比,在灵活性上,Maven较为死板的配置方式有时会造成定制化困难。在Build性能比较中,Gradle表现的也相当优异。由于使用了特定领域强化的语言Groovy,在编写Build脚本时所带来的体验也是XML所无法比拟的。 Gradle的缺点:Gradle目前看来只是比较适合小型项目的开发,有时候Gradle所带来的过于的便捷性反而会成为绊脚石,在组织上会带来一些不便。 考虑到项目变大的时候,XML形式的配置文件虽然较为复杂,但易于维护的特性,并且相较于Gralde,我还是比较熟悉Maven,故选择Maven做依赖维护。 2.ORM框架 Hibernate:作为老牌超重型ORM框架,Hibernate带来了便捷的ORM映射方式,可以使开发者迅速建立起DataSource映射,远离复杂的数据映射过程。但是由于其过于臃肿,在超大量数据读写时可能会造成性能瓶颈。 Mybatis:新兴的ORM框架Mybatis与其说是一个完整的ORM框架,倒不如说是一个ORM半成品,高级查询还是要开发者手动编写SQL,不过这也是Mybatis有用的地方,在大量数据读写的场景下,手动编写SQL查询语句往往可以带来更好的性能表现。 考虑到本应用并不是在高吞吐环境下使用,并且配合新JPA规范的Hibernate用起来也相当顺手,故选择Hibernate当作项目的ORM框架。  3.Spring Boot / Dropwizard 依赖对比: 在依赖选择上,Spring Boot拥有更大的空间,并且Spring全家桶的发展状况也越来越好,不失为一个很好的选择。 从Github生态来看,截止目前(2018/3/8),Spring Boot在Github上拥有21.8K Star,16.9K Fork,而Dropwizard则有6.41K Star,477 Fork。 所以无论从社区生态,依赖选择空间还是发展前景来看,Spring Boot都是一个不错的选择。

Csgopolygon Withdraw Assistant扫货插件开发日志

Github: https://github.com/SolitudeRA/CSGOPolygon-withdraw-assistant 最近GO群里的大商又有了新需求,因为需要在赌狗网站上扫货,并且货物信息一直在变,而且竞争激烈,所以又找到了我,要做一个能显示每次刷新之后新出来的货物的Chrome插件。虽然最近比较忙,不过在一番准备之后,历经半个月,终于是拿出了一个基本能用的0.9Beta版,期间踩了很多坑,并且还有不少未解决的奇怪问题,所以写篇日志,整理如下: 首先,由于网站本身需要先经过Google的人机验证才能将货物页面刷新出来,所以为了节省系统资源与减少未知的错误,还是使用了与上一个插件相同的被动监听策略,也就是Mutation Observer。不过,有一点不同的是,因为创建了新的div来存放新出现的货物,导致原来在货物div的绑定的监听事件全部失效,并且货物要可以在不同div之间来回移动,所以需要动态绑定click事件到新添加的元素上。为了实现这一点,我用到了Mutation Observer的另外一个特性–Mutation Record。简单来说,Mutation Record可以作为第一个参数来传递给Mutation Observer的回调函数,用来记录发生在观察对象上的DOM变化。通过调用Mutation Record的addedNodes属性,可以获得DOM行为中被添加的DOM对象,这使得我可以动态的为对象绑定click事件。不过,第一个坑就在这里,我原以为每次传给回调函数的是一个单一的Mutation Record对象,DOM树每改变一次就触发一次,其中包含着每次DOM变动的记录,结果与我预想的不同,Mutation Observer的回调函数是在所有DOM变动完成后才触发,并且返回的是一个Mutation Record数组,数组长度与变动次数相符。不过这个坑比较浅,多用几次console.log()来观察就可以避过这个坑,完成版函数如下: let observerRight = new MutationObserver(function (mutationRecord) { let addedNode = mutationRecord[1].addedNodes[0]; if ($(addedNode).hasClass(“slot-right-ext”)) { $(addedNode).on(“click”, function () {Continue readingCsgopolygon Withdraw Assistant扫货插件开发日志

csgo.exchange磨损查询插件开发日志#2

Github:https://github.com/SolitudeRA/CSGO.exchange-Autoretrieve 经过了一次大的迭代更新,插件的版本号来到了2.0(上版本日志在这里),代码主体全部重构,并且将语言规范升级到了ECMAScripts 6,之前的点击动作触发全部是通过主动监听来完成的,比如这样: var IntervalHandler1 = window.setInterval(function () { if ($(“.msgNotif”) !== null) { $(“.msgNotif”).detach(); $(“.widw-close”).click(); setTimeout(function () { $widw.css(“display”, “none”); $bgwidw.css(“display”, “none”); currentNode.append(“<div class=’show-rawext’>success</div>”); window.clearInterval(IntervalHandler1); controller(node, reloadFlag); }, 100);Continue readingcsgo.exchange磨损查询插件开发日志#2