![加密通訊聊天平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn) - 以 WEB 平臺(tái)為例_第1頁](http://file4.renrendoc.com/view12/M0A/06/1C/wKhkGWYBBPGAKny6AAHLfmTGKRc247.jpg)
![加密通訊聊天平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn) - 以 WEB 平臺(tái)為例_第2頁](http://file4.renrendoc.com/view12/M0A/06/1C/wKhkGWYBBPGAKny6AAHLfmTGKRc2472.jpg)
![加密通訊聊天平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn) - 以 WEB 平臺(tái)為例_第3頁](http://file4.renrendoc.com/view12/M0A/06/1C/wKhkGWYBBPGAKny6AAHLfmTGKRc2473.jpg)
![加密通訊聊天平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn) - 以 WEB 平臺(tái)為例_第4頁](http://file4.renrendoc.com/view12/M0A/06/1C/wKhkGWYBBPGAKny6AAHLfmTGKRc2474.jpg)
![加密通訊聊天平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn) - 以 WEB 平臺(tái)為例_第5頁](http://file4.renrendoc.com/view12/M0A/06/1C/wKhkGWYBBPGAKny6AAHLfmTGKRc2475.jpg)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
廣東東軟學(xué)院本科生畢業(yè)設(shè)計(jì)(論文)摘要21世紀(jì)是信息時(shí)代,隨著計(jì)算機(jī)技術(shù)、多媒體技術(shù)和互聯(lián)網(wǎng)技術(shù)的飛速發(fā)展,我們足不出戶就能夠聯(lián)系到處于世界另一個(gè)角落的朋友,獲取世界各地的信息。IM(InstantMessaging,即時(shí)通訊)應(yīng)用已經(jīng)成為人們交流溝通必備的工具。為國人熟知的就有QQ、weChat等。QQ和weChat等IM軟件發(fā)展到今天,已經(jīng)具備完善的通訊功能,簡單易用且隨時(shí)隨地。但一些特定行業(yè)單位,比如國安部門、軍隊(duì)單位、軍品研究生產(chǎn)單位或者有商業(yè)機(jī)密和研發(fā)機(jī)密的需求的一些公司,出于其安全性和保密性的要求,其辦公網(wǎng)絡(luò)是與Internet完全物理隔離的。那么為這些特定企業(yè)設(shè)計(jì)和開發(fā)即時(shí)通訊系統(tǒng)就顯得非常重要和必要。本次畢業(yè)設(shè)計(jì)的加密通訊聊天平臺(tái),以AES加密算法和RSA加密算法相結(jié)合實(shí)現(xiàn)信息加密,論文具體介紹整個(gè)系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)過程,使用Layer、BootstrapJQuery開發(fā)前端界面,SpringBoot搭建后端框架。關(guān)鍵詞:SpringBoot;Shiro;WebSocket;AES加密;RSA加密 AbstractThe21stcenturyistheinformationage.Withtherapiddevelopmentofcomputertechnology,multimediatechnologyandInternettechnology,wecanreachfriendsinanothercorneroftheworldandgetinformationfromallovertheworldwithoutleavinghome.IM(InstantMessaging,instantmessaging)applicationhasbecomeanessentialtoolforpeopletocommunicate.QQandweChatarewell-knowntothepeople.WiththedevelopmentofIMsoftwaresuchasQQandweChattothisday,italreadyhasacompletecommunicationfunction,whichissimpleandeasytouse,anytime,anywhere.However,somespecificindustryunits,suchasnationalsecuritydepartments,militaryunits,militaryproductresearchandproductionunits,orsomecompanieswiththeneedsofcommercialsecretsandresearchanddevelopmentsecrets,becauseoftheirsecurityandconfidentialityrequirements,theirofficenetworkiscompletelyphysicallyisolatedfromtheInternetof.Soitisveryimportantandnecessarytodesignanddevelopinstantmessagingsystemsforthesespecificenterprises.ThegraduatedencryptedcommunicationchatplatformusesAESencryptionalgorithmandRSAencryptionalgorithmtoachieveinformationencryption.Thethesisspecificallyintroducesthedesignandimplementationprocessoftheentiresystem,usesLayerandBootstrapJQuerytodevelopthefront-endinterface,andSpringBootbuildstheback-endframework.Keywords:SpringBoot;Shiro;WebSocket;AES;RSA
目錄第一章緒論 7第二章相關(guān)理論知識(shí) 92.1開發(fā)環(huán)境和技術(shù)選型 92.2SpringBoot 92.2.1SpringBoot簡介 92.3ApacheShiro 102.3.1可靠的安全框架 102.3.2總結(jié)shiro的三板斧 102.4.3UsernamePasswordToken 112.4.4ShiroConfig配置類 112.4.5Realm 12第三章關(guān)鍵技術(shù)研究 123.1WebSocket 123.1.1WebSocket簡介 123.1.2系統(tǒng)WebSocket事務(wù)圖 133.1.3WebSocket工作原理 133.2加密算法 143.2.1AES加密 143.2.2RSA加密 15第四章系統(tǒng)功能需求 154.1注冊(cè)/登錄模塊 154.1.1用戶注冊(cè) 154.1.2用戶登錄 164.1.3微信第三方登錄 174.2通信模塊 184.3加密模塊 18第五章系統(tǒng)具體實(shí)現(xiàn) 195.1系統(tǒng)架構(gòu)設(shè)計(jì) 195.2系統(tǒng)功能設(shè)計(jì) 205.3數(shù)據(jù)庫設(shè)計(jì) 205.3.1數(shù)據(jù)庫E-R圖 205.3.2數(shù)據(jù)庫表設(shè)計(jì) 215.4.2項(xiàng)目目錄 255.5關(guān)鍵代碼實(shí)現(xiàn) 265.5.1Shiro實(shí)現(xiàn)免密登錄 265.5.2微信掃碼登錄 365.5.4AES加密實(shí)現(xiàn) 455.5.5項(xiàng)目演示截圖 48第六章項(xiàng)目總結(jié) 52參考文獻(xiàn) 52致謝 53第一章緒論研究背景和意義1946年2月14日,世界上第一臺(tái)通用計(jì)算機(jī)“ENIAC”在賓夕法尼亞大學(xué)被發(fā)明出世。1969年6月,世界上第一個(gè)采用分組交換技術(shù)組件的網(wǎng)絡(luò)誕生,即“阿帕網(wǎng)”,后又發(fā)展為今天的互聯(lián)網(wǎng)。隨著計(jì)算機(jī)技術(shù)、多媒體技術(shù)和互聯(lián)網(wǎng)技術(shù)的快速發(fā)展,改變了人與人之間從古時(shí)的車馬郵件,飛鴿傳書的通訊方式,人們之間的溝通方式更加多元。IM(InstantMessaging,即時(shí)通訊)因應(yīng)而生并飛速發(fā)展。IM系統(tǒng)允許用戶可以隨時(shí)使用網(wǎng)絡(luò)實(shí)地通信,即時(shí)性是其最大的優(yōu)點(diǎn),只要雙方同時(shí)在線,即可實(shí)現(xiàn)交流通訊。眾所周知,18至19世紀(jì)是蒸汽時(shí),一切發(fā)展的動(dòng)力源于蒸汽;19至20世紀(jì)是電氣時(shí)代,電的發(fā)現(xiàn)以及電機(jī)等以電驅(qū)動(dòng)的各類設(shè)備的發(fā)明與使用,推動(dòng)著整個(gè)世界的生產(chǎn)邁向自動(dòng)化,機(jī)械化。20至21世紀(jì)無疑就是信息時(shí)代,隨著計(jì)算機(jī)技術(shù)、多媒體技術(shù)和互聯(lián)網(wǎng)技術(shù)的飛速發(fā)展,我們足不出戶就能夠聯(lián)系到處于世界另一個(gè)角落的朋友,獲取世界各地的信息。IM系統(tǒng)已經(jīng)成為人們交流溝通必備的工具。第一個(gè)即時(shí)通訊工具是幾個(gè)以色列青年在1996年11月發(fā)明的。ICQ是英文ISEEKYOU我找你的諧音。因?yàn)橹袊尤牖ヂ?lián)網(wǎng)年份較晚,所以ICQ并不為中國普通大眾所熟知。與ICQ有著異曲同工的QQ,則是家喻戶曉的的IM產(chǎn)品,其優(yōu)良的軟件性能和免費(fèi)特性,深受用戶喜愛。隨后誕生的微信,亦長江后浪推前浪。QQ和微信已是中國人民不可或缺的通訊工具。QQ、微信、阿里旺旺等通訊軟件都是基于用戶安裝客戶端軟件,即C/S架構(gòu)而存在。雖然之后推出了網(wǎng)頁網(wǎng)版,但閹割了其大部分功能,要想有良好的用戶體驗(yàn),還是需要下載并安裝其軟件到電腦里或者手機(jī)里。如果設(shè)備里沒有安裝軟件,或者要聯(lián)系的人沒有安裝軟件,那么就就會(huì)有一個(gè)等待安裝的限制,便利性受到約束。而且沒一次軟件新功能的推出,都需要用戶去升級(jí)軟件,很大程度上并不能照顧到所有用戶。隨著網(wǎng)頁WEB技術(shù)的發(fā)展,更多的軟件脫離了C/S架構(gòu)模式,轉(zhuǎn)為B/S架構(gòu)。而WebSocket的出現(xiàn),也為IM系統(tǒng)設(shè)計(jì)成B/S架構(gòu)提供了可能。采用B/S架構(gòu)的IM工具,用戶就可以擺脫下載軟件安裝軟件才能使用軟件的桎梏,只要電腦里、手機(jī)里有可以訪問網(wǎng)頁的瀏覽器,即可以使用其進(jìn)行通訊交流,不必考慮設(shè)備差異。當(dāng)下互聯(lián)網(wǎng)WEB應(yīng)用在市場(chǎng)的比重占有率逐步升高,且隨著移動(dòng)互聯(lián)的發(fā)展,WEB應(yīng)用的多終端兼容實(shí)現(xiàn)的優(yōu)勢(shì)也充分體現(xiàn)。相較于傳統(tǒng)C/S架構(gòu),B/S架構(gòu)有以下優(yōu)點(diǎn):輕量化開發(fā)、易維護(hù)更新、受眾面廣、簡化用戶使用流程、界面美觀、良好的兼容性等。設(shè)計(jì)思路雖說是加密聊天通訊工具,但其功能實(shí)現(xiàn)也不外乎是傳統(tǒng)IM工具的所應(yīng)具備的能力。如基本聊天功能,用戶登錄與注冊(cè)功能,文件傳輸功能等?;诠δ軐?shí)現(xiàn)屬性,我將分為以下幾個(gè)模塊:用戶注冊(cè)/登錄模塊、私聊/群聊模塊、日志模塊、系統(tǒng)模塊、公共文件模塊、加密功能模塊、好友模塊、個(gè)人信息模塊。其中聊天模塊主要實(shí)現(xiàn)P2P私人聊天和建群群聊功能,文件和圖片傳輸功能。該系統(tǒng)后端將基于SpringBoot框架開發(fā),技術(shù)選型為:Java,MyBatis,WebSocket,WebRTC等;前端頁面設(shè)計(jì)基于Bootstrap4,Jquery,Layer等;數(shù)據(jù)庫選用Mysql5.7;版本控制即打包使用Maven;加密功能模塊暫定為AES加密和RSA加密雙結(jié)合實(shí)現(xiàn)信息加密處理,具體過程為:聊天信息為AES對(duì)稱加密,但要對(duì)AES密鑰用對(duì)方的RSA公鑰加密。雙方在得到加密信息后,需要用自己的密鑰解密被RSA加密過的AES密鑰,并用這個(gè)AES密鑰解密被AES加密的信息。這樣一來,傳輸?shù)臄?shù)據(jù)都是密文,且只有秘鑰才能解密。以此來達(dá)到更為安全的加密效果。論文整體結(jié)構(gòu)結(jié)構(gòu)安排如下:第一章:緒論。介紹本系統(tǒng)的研究背景和意義,簡述系統(tǒng)內(nèi)容和結(jié)構(gòu)安排第二章:相關(guān)理論知識(shí)。對(duì)系統(tǒng)開發(fā)中相關(guān)技術(shù)進(jìn)行介紹,主要包括、SpringBoot、Maven、Shiro、Redis等第三章:關(guān)鍵技術(shù)研究,對(duì)系統(tǒng)關(guān)鍵技術(shù)WebSocket、AES加密技術(shù)、RSA加密技術(shù)進(jìn)行叫詳細(xì)說明第四章:對(duì)系統(tǒng)功能模塊進(jìn)行圖例演示,闡述系統(tǒng)概要設(shè)計(jì)第五章:系統(tǒng)實(shí)現(xiàn)第六章:項(xiàng)目演示和總結(jié)第七章:文獻(xiàn)綜述第二章相關(guān)理論知識(shí)2.1開發(fā)環(huán)境和技術(shù)選型操作系統(tǒng):Windows10操作系統(tǒng);數(shù)據(jù)庫:mysql-5.7;Java環(huán)境:JDK1.8;瀏覽器:MicrosoftEdgeBeta開發(fā)工具:IntelliJIDEA2019.2.3x64、Navicat12forMySQL系統(tǒng)環(huán)境:JavaEE8、Servlet3.0、ApacheMaven3主框架:SpringBoot2.0、SpringFramework5.0、ApacheShiro1.4持久層:ApacheMyBatis3.4、AlibabaDruid1.1視圖層Bootstrap4、Thymeleaf3.02.2SpringBoot2.2.1SpringBoot簡介SpringBoot是一個(gè)java開發(fā)框架,它簡化用Spring開發(fā)應(yīng)用的時(shí)候,繁瑣的搭建過程。SpringBoot其實(shí)不是一個(gè)全新的產(chǎn)品,我們可以從它身上看到前輩SSH和SSM的影子。它默認(rèn)配置了很多框架的使用方式,例如Mybatis、Shiro等等,就像mave可以整合所有的jar包一樣2.2.2為什么使用SpringBootSpringBoot之前SSM框架或其他Spring框架,在整合其他功能框時(shí)都需要配置文件,這導(dǎo)致項(xiàng)目中的配置文件越來越多,內(nèi)容越來越繁雜。項(xiàng)目中常常因?yàn)榕渲梦募鲥e(cuò)的原因,導(dǎo)致項(xiàng)目運(yùn)行出錯(cuò)。SpringBoot的出現(xiàn),解決開發(fā)框架的繁雜配置。SpringBoot約定大于配置的理念,使它能快速整合第三方框架,減少甚至不需要配置文件。對(duì)于一個(gè)開發(fā)團(tuán)隊(duì)來說,極大減少工作成本、更加利于開發(fā),且后期維護(hù)也更加簡單。2.3ApacheShiro2.3.1可靠的安全框架ApacheShiro是一個(gè)Java安全框架,提供了認(rèn)證、授權(quán)、加密和會(huì)話管理等功能,對(duì)于任何一個(gè)應(yīng)用程序,Shiro都可以提供全面的安全管理服務(wù)。Authentication的身份認(rèn)證/登錄,驗(yàn)證某個(gè)已認(rèn)證的用戶是否擁有某個(gè)權(quán)限;SessionManager:會(huì)話管理,用戶登錄后在沒有退出之前,它的所有信息都在會(huì)話中。對(duì)Web開發(fā)十分友善;Cryptography:加密,保護(hù)數(shù)據(jù)的安全性,如密碼加密存儲(chǔ)到數(shù)據(jù)庫,而不是明文存儲(chǔ);Caching:緩存,比如用戶登錄后,其用戶信息、擁有的角色/權(quán)限不必每次去查,這樣可以提高效率;我的認(rèn)知是:Shiro是一套安全認(rèn)證和權(quán)限管理框架,而不是一個(gè)取之能用的工具。既然是框架,Shiro就不會(huì)去主動(dòng)維護(hù)用戶、維護(hù)權(quán)限;簡而言之,架子人家給搭好了,而登錄驗(yàn)證邏輯,權(quán)限賦予邏輯等等之類“里子”需要我們自己去填2.3.2總結(jié)shiro的三板斧一個(gè)完整的Shiro業(yè)務(wù),必須包括Subject、SecurityManager、Realm,我稱之為shiro的三板斧,打完即收工:Subject:主體,代表了當(dāng)前“用戶”;所有Subject都會(huì)綁定到SecurityManager,且與Subject的所有交互都會(huì)委托給SecurityManager;Subject更多只是一個(gè)門面作用;SecurityManager才是實(shí)際的執(zhí)行者;SecurityManager:安全管理器;所有與安全有關(guān)的操作都會(huì)與SecurityManager交互;可以看出它是Shiro的核心;Realm:域,誰來負(fù)責(zé)和數(shù)據(jù)庫進(jìn)行交互呢?Realm!誰來給用戶做身份認(rèn)證和賦予權(quán)限呢?Realm!也就是說SecurityManager要做的操作,其實(shí)都是交于Realm的2.4.3UsernamePasswordToken實(shí)現(xiàn)過程中我們可能會(huì)碰到這個(gè)家伙,它用于將用戶輸入的用戶名和密碼封裝成token;普通的登錄無非就是輸入賬號(hào)密碼??梢酝ㄟ^調(diào)用getPrincipal()方法來獲取token中的用戶名并以此來進(jìn)行登錄驗(yàn)證;實(shí)質(zhì)就是通過調(diào)用本地getUserName()方法直接獲取存儲(chǔ)在token中的username。credentials:證明/憑證,即只有主體知道的安全值,如密碼/數(shù)字證書等;可以通過getCredentials()方法來獲取token中的密碼,該方法與獲取用戶名的方式一致,調(diào)用本地getPassword()方法獲取存儲(chǔ)在token中的密碼由此可見UsernamePasswordToken的重要性;這個(gè)類同時(shí)繼承了HostAuthenticationToken及RememberMeAuthenticationToken,因此UsernamePasswordToken能夠存儲(chǔ)客戶端的主機(jī)地址以及確定token是否能夠被后續(xù)的方法使用(即登錄時(shí)的‘“記住我”’)。出信息安全考慮,驗(yàn)證完成后通常會(huì)調(diào)用clear方法清除token數(shù)據(jù),其中對(duì)用戶密碼(password)的處理較為特殊,UsernamePasswordToken不是單純地:“password=null”,而是先將password引用對(duì)應(yīng)的char數(shù)組的值全部置0,然后斷開調(diào)用。2.4.4ShiroConfig配置類shiro做什么?怎么做?很大一部分(甚至可以說完全)由shiroConfig約定而為。簡單點(diǎn),shiroConfig就是shiro一個(gè)配置類,類似于以前的xml。林林總總有個(gè)多配置,個(gè)人覺得以下幾個(gè)配置在配置類中比較重要:安全管理器SecurityManager、shiro攔截器、自定義Realm(后期要做第三方)、session管理器。SecurityManager在前邊講過,作為shiro的核心,主要協(xié)調(diào)Shiro內(nèi)部的各種安全組件。我在使用過程中,接觸到的主要是用來配置realmshiro攔截器(shiroFilter)**可以用設(shè)置各個(gè)頁面的訪問權(quán)限,一般在為進(jìn)過shiro認(rèn)證之前,這里只會(huì)放行登錄/注冊(cè)操作頁面,錯(cuò)誤頁面,登出頁面和一些靜態(tài)文件。2.4.5RealmShiro的認(rèn)證和授權(quán)操作,是由realm類來實(shí)現(xiàn)的;一般這個(gè)類是自己自定義的。自定義的Realm類要繼承AuthorizingRealm類,并且重載doGetAuthorizationInfo和doGetAuthenticationInfo兩個(gè)方法。第三章關(guān)鍵技術(shù)研究3.1WebSocket3.1.1WebSocket簡介WebSocket是一種網(wǎng)絡(luò)傳輸協(xié)議,可在單個(gè)TCP連接上進(jìn)行全雙工通信,位于OSI模型的應(yīng)用層,和HTTP一樣基于TCP傳輸。但WebSocket是全雙工傳輸形式,也就是說可以實(shí)現(xiàn)客戶端和服務(wù)器之間雙向交流,客戶端實(shí)時(shí)了解服務(wù)器數(shù)據(jù)變化,這種形式特別適合用來做聊天程序。WebSocket最大特點(diǎn)就是,服務(wù)器可以主動(dòng)向客戶端推送信息,客戶端也可以主動(dòng)向服務(wù)器發(fā)送信息,是真正的雙向平等對(duì)話,這種情況下可以實(shí)現(xiàn):較少的控制開銷、更強(qiáng)的實(shí)時(shí)性、保持連接狀態(tài)、數(shù)據(jù)格式比較輕量,性能開銷小,通信高效。建立在TCP協(xié)議之上,服務(wù)器端的實(shí)現(xiàn)比較容易。3.1.2系統(tǒng)WebSocket事務(wù)圖3.1.3WebSocket工作原理WEB服務(wù)端開啟WebSocket服務(wù)并等待客戶端用戶連接。瀏覽器創(chuàng)建WebSocket類對(duì)象并向服務(wù)端請(qǐng)求連接。WEB服務(wù)器觸發(fā)WebSocketService的createWebSocketInbound方法并接受數(shù)據(jù),創(chuàng)建對(duì)應(yīng)onOpen方法。WEB服務(wù)器判斷連接是否創(chuàng)建成功,如失敗執(zhí)行步驟5,成功執(zhí)行步驟6連接創(chuàng)建失敗,觸發(fā)客戶端error回調(diào)函數(shù),結(jié)束WebSocket連接連接創(chuàng)建成功,觸發(fā)客戶端onopen回調(diào)函數(shù),完成WebSocket連接客戶端通過send方法發(fā)送數(shù)據(jù)到WEB服務(wù)器WEB服務(wù)器觸發(fā)onMessage方法接受客戶端數(shù)據(jù)WEB服務(wù)器通過sendMessage方法像客戶端發(fā)送數(shù)據(jù)客戶端觸發(fā)onMessage回調(diào)函數(shù)接收數(shù)據(jù)并進(jìn)行相關(guān)操作客戶端通過調(diào)用close方法關(guān)閉WebSocket連接服務(wù)器觸發(fā)onClose方法進(jìn)行關(guān)閉連接操作,結(jié)束WebSocket連接3.2加密算法3.2.1AES加密AES是最流行的對(duì)稱加密算法,對(duì)信息的加密和解密用的是同一套密鑰。加密之初會(huì)把文件切分成一個(gè)個(gè)128位,的小塊進(jìn)行加密。如果文件大小不是16字節(jié)的整數(shù)倍,那就要在末尾添加一些數(shù)據(jù)湊夠。AES有兩個(gè)輸入一個(gè)輸出,輸出是密文,輸入自然是密鑰和明文。輸出是明文,輸入自然就是密鑰和密文。當(dāng)然具體的加解密過程十分復(fù)雜。AES是非常安全的,最短的密鑰也會(huì)有128位,大部分密鑰長度會(huì)比128位大。密鑰越長也就越安全,但隨之加解密的速度就越慢。。AES加密非常常用,很多CPU在硬件層面上都會(huì)支持AES的加解密,https就是使用AES來進(jìn)行數(shù)據(jù)的加密的,因?yàn)锳ES是TLS和SSL標(biāo)準(zhǔn)的一部分。3.2.2RSA加密對(duì)稱加密和非對(duì)稱加密是密不可分的。AES是對(duì)稱加密,而RSA則是非對(duì)稱加密算法。如果沒有RSA算法,現(xiàn)在的網(wǎng)絡(luò)世界可以說毫無安全可言。ssh協(xié)議也是基于RSA加密算法才能確保通訊是加密的,可靠的。非對(duì)稱加密算法的加密解密過程是這樣的:1)用戶A使用RSA算法生成兩把密鑰,就是公鑰和私鑰。顧名思義,公鑰就是公開的,私鑰就是自己保存的。2)用戶B想對(duì)用戶A發(fā)送加密信息,用戶B可以輕松獲取到用戶A的公鑰,然后用它對(duì)信息加密。3)用戶A得到加密后的信息,用自己的私鑰解密。這樣每個(gè)人都可以利用公鑰發(fā)送加密消息,而只有擁有秘鑰的接收方才能解讀密文看到原消息。第四章系統(tǒng)功能需求我將系統(tǒng)總體功能分為以下幾個(gè)模塊:用戶登錄/注冊(cè)、用戶信息更改、頭像文件上傳、在線多人群聊、在線私聊、系統(tǒng)日志記錄、聊天內(nèi)容加密傳輸。4.1注冊(cè)/登錄模塊4.1.1用戶注冊(cè)用戶注冊(cè)拋棄傳統(tǒng)的用戶自由定義帳號(hào)密碼進(jìn)行注冊(cè),改為現(xiàn)流行的手機(jī)號(hào)注冊(cè)新用戶,即用戶通過手機(jī)號(hào)接收短信驗(yàn)證碼實(shí)現(xiàn)注冊(cè),因?yàn)槭謾C(jī)號(hào)注冊(cè)均為個(gè)人實(shí)名注冊(cè),這就保證了帳號(hào)的唯一性和真實(shí)性。方便用戶維護(hù)和管理;具體流程為下圖:4.1.2用戶登錄短信登錄:因?yàn)橛脩糇?cè)的時(shí)候用的是手機(jī)號(hào),用戶在注冊(cè)成功后,可以通過手機(jī)號(hào)接收登錄驗(yàn)證碼進(jìn)行登錄。帳號(hào)密碼登錄:用戶在注冊(cè)時(shí)設(shè)置的密碼,即用戶的登錄密碼,用戶可以通過手機(jī)號(hào)加登錄密碼進(jìn)行登錄。第三方登錄:用戶可以給帳號(hào)綁定第三方帳號(hào),實(shí)現(xiàn)第三方帳號(hào)登錄4.1.3微信第三方登錄第三方登錄我選用應(yīng)用較為廣泛的微信掃碼登錄。即帳號(hào)可以和用戶自己的微信帳號(hào)進(jìn)行綁定,實(shí)現(xiàn)微信掃碼登錄本IM系統(tǒng)。在這個(gè)項(xiàng)目中,微信第三方登錄的關(guān)鍵點(diǎn),即用戶的系統(tǒng)賬號(hào)和微信號(hào)的綁定??傮w可以分為一下三個(gè)步驟:對(duì)于系統(tǒng)賬戶與微信的綁定,我的思路是:若是沒有綁定過微信的用戶掃碼登錄,即提示其先賬號(hào)密碼登錄,系統(tǒng)自動(dòng)更新Auth表信息;若未未注冊(cè)用戶,則提示其注冊(cè),注冊(cè)時(shí)自動(dòng)更新第三方登錄表信息。但掃碼登錄只是登錄的一種,更多的時(shí)候用戶只是執(zhí)行簡單的登錄或者注冊(cè);所以我引入了redis服務(wù)。? 當(dāng)一個(gè)用戶是先掃碼再登錄/注冊(cè)的,我會(huì)在redis保存其openId和unionId信息,執(zhí)行登錄/注冊(cè)操作時(shí),先去redis取值,如果存在openId和unionId,說明用戶此時(shí)是在執(zhí)行綁定微信操作,綁定微信操作完成后清除redis中的openId和unionId信息。這樣就可以很簡單的區(qū)分用戶是在進(jìn)行普通的登錄注冊(cè)或者綁定微信的登錄注冊(cè)了。? 怎么確保每一個(gè)掃碼綁定微信的用戶,能從redis拿到屬于自己的openId和unionId呢?可以用第一步請(qǐng)求到的code,開放平臺(tái)給的微信授權(quán)臨時(shí)票據(jù)。結(jié)合code作為對(duì)應(yīng)的openId和unionI在redis的key,可以確保每一個(gè)用戶拿到對(duì)應(yīng)的唯一的openId和unionId。4.2通信模塊在線多人群聊、在線私聊的實(shí)現(xiàn)相對(duì)簡單,在WebSocket連接成功的情況下,WebSocket基本可以完成以上功能。用戶的聊天記錄信息都會(huì)在加密后實(shí)時(shí)保存在Redis服務(wù)器中,當(dāng)用戶退出系統(tǒng)后,系統(tǒng)將會(huì)獲取Redis中的聊天信息,保存到數(shù)據(jù)庫中。用戶下次登錄,服務(wù)器將從數(shù)據(jù)庫獲取對(duì)應(yīng)的加密聊天記錄,解密后回顯指用戶界面。具體流程圖如下4.3加密模塊加密功能模塊暫定為AES加密和RSA加密雙結(jié)合實(shí)現(xiàn)信息加密處理,即其登錄信息和聊天信息為AES對(duì)稱加密,但要對(duì)其解密密鑰實(shí)現(xiàn)RSA加密傳輸,即客戶端和服務(wù)器通過RSA算法各自生成一套公鑰和私鑰,并交換公鑰。信息被AES算法加密,AES的key被RSA算法加密。雙方在得到加密信息后,需要用對(duì)方的公鑰解密被RSA加密過的key,并用這個(gè)key解密被AES加密的信息。這樣一來,傳輸?shù)臄?shù)據(jù)都是密文,且只有秘鑰才能解密。以此來達(dá)到更為安全的加密效果。第五章系統(tǒng)具體實(shí)現(xiàn)5.1系統(tǒng)架構(gòu)設(shè)計(jì)系統(tǒng)采用經(jīng)典的B/S架構(gòu)體系,即三層架構(gòu)體系。分別為表現(xiàn)層(UI)、業(yè)務(wù)邏輯層(BBL)和數(shù)據(jù)訪問層(DAL)。而項(xiàng)目的設(shè)計(jì)模式也是較為傳統(tǒng)實(shí)用的MVC模式,即Model(模型),View(視圖),Controller(控制)。1)表現(xiàn)層:主要負(fù)責(zé)展示系統(tǒng)業(yè)務(wù)和數(shù)據(jù),實(shí)例化用戶的業(yè)務(wù)操作;較為通俗的說法即前端頁面展示。我將使用HTML5、Jquery、Bootstrap和Thymeleaf實(shí)現(xiàn)。2)業(yè)務(wù)邏輯層:作為連接前端和數(shù)據(jù)庫數(shù)據(jù)的中間媒介,業(yè)務(wù)邏輯層極為重要,它將表現(xiàn)層,即前端用戶的操作行為和數(shù)據(jù)請(qǐng)求進(jìn)行處理,與數(shù)據(jù)庫做數(shù)據(jù)交互,將處理結(jié)果返回表現(xiàn)層。起著中間樞紐的重要作用。MVC設(shè)計(jì)模式也在該層有極大的體現(xiàn)3)數(shù)據(jù)訪問層:原始數(shù)據(jù)的操作層,對(duì)原始數(shù)據(jù)進(jìn)行操作,具體的功能是為表現(xiàn)層以及業(yè)務(wù)邏輯層提供需要得數(shù)據(jù)服務(wù)。5.2系統(tǒng)功能設(shè)計(jì)5.3數(shù)據(jù)庫設(shè)計(jì)5.3.1數(shù)據(jù)庫E-R圖用戶與系統(tǒng)日志用戶與用戶日志用戶和在線用戶表5.3.2數(shù)據(jù)庫表設(shè)計(jì)表1用戶表用戶表(Employee)字段名意義數(shù)據(jù)類型寬度是否可為空主鍵id用戶idvarchar64否√login_name登錄賬戶varchar100否nick_name用戶昵稱varchar100是salt鹽varchar100是password用戶密碼varchar100是phonenumber電話號(hào)碼varchar100是sex性別char10是age年齡int100是head_profile頭像文件char11是profile個(gè)人簡介varchar255是last_time最后登錄時(shí)間varchar64是status帳號(hào)狀態(tài)char2是del_flag刪除標(biāo)志char2是create_time注冊(cè)時(shí)間varchar64是表2在線用戶表在線用戶表(user_online)字段名意義數(shù)據(jù)類型寬度是否可為空主鍵sessionId用戶會(huì)話idvarchar50否√login_name登錄賬號(hào)varchar50否ipaddr登錄IP地址varchar50是browser瀏覽器類型varchar50是os操作系統(tǒng)varchar50是status在線狀態(tài)varchar10是last_time最后訪問時(shí)間varchar50是create_tiem創(chuàng)建時(shí)間varchar50是表3系統(tǒng)日志表在線用戶表(logininfor)字段名意義數(shù)據(jù)類型寬度是否可為空主鍵info_id訪問IDvarchar50否√login_name登錄賬號(hào)varchar50否ipaddr登錄IP地址varchar50是browser瀏覽器類型varchar50是os操作系統(tǒng)varchar50是status登錄狀態(tài)varchar10是msg提示消息varchar50是login_time創(chuàng)建時(shí)間varchar50是表4第三方登錄表第三方登錄表(auth_login)字段名意義數(shù)據(jù)類型寬度是否可為空主鍵id主鍵varchar64否√open_id第三方標(biāo)識(shí)varchar200否union_id用戶統(tǒng)一標(biāo)識(shí)varchar200是app_type第三方平臺(tái)varchar100是user_id用戶idvarchar64是status賬號(hào)狀態(tài)char2是create_time創(chuàng)建時(shí)間datetime0是5.4系統(tǒng)代碼實(shí)現(xiàn)5.4.1引入jar包===========================代碼開始==========================<java.version>1.8</java.version><thymeleaf.version>3.0.11.RELEASE</thymeleaf.version><thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version><druid.version>1.1.14</druid.version><commons.lang3.version>3.8</commons.lang3.version><mysql.version>5.1.47</mysql.version><mybatis.version>2.1.1</mybatis.version><shiro.version>1.4.0</shiro.version><snakeyaml.version>1.25</snakeyaml.version><userAgentUtils.version>1.21</userAgentUtils.version><spring.session>1.3.5.RELEASE</spring.session><fastjson.version>1.2.68</fastjson.version><gson.version>2.8.6</gson.version><hettpclient.vesion>4.5.10</hettpclient.vesion><commons-pool2.version>2.6.1</commons-pool2.version><hutool-log.version>5.3.0</hutool-log.version><shiro.version>2.0.0</shiro.version><hutool-core.version>5.2.0</hutool-core.version><shiro-ehcache.version>1.5.0</shiro-ehcache.version><aspectjweaver.version>1.9.5</aspectjweaver.version>===========================代碼開始==========================5.4.2項(xiàng)目目錄5.5關(guān)鍵代碼實(shí)現(xiàn)5.5.1Shiro實(shí)現(xiàn)免密登錄由于項(xiàng)目要集成第三方登錄,我在shiro原有的賬號(hào)密碼登錄認(rèn)證的基礎(chǔ)上,多寫了一個(gè)免密登錄的Realm,當(dāng)用戶授權(quán)第三方拿到身份認(rèn)證后,可以跳過原有的賬號(hào)密碼認(rèn)證來登錄系統(tǒng),實(shí)現(xiàn)第三方登錄。可以從寫一個(gè)登錄模式枚舉開始===========================代碼開始==========================/**
*登錄模式
*@authorpong
*/
publicenumLoginType{
//密碼登錄
PASSWORD("Normal"),
//免密登錄
NOPASSWD("Free");
privateStringcode;
//狀態(tài)值
LoginType(Stringcode){
this.code=code;
}
publicStringgetCode(){
returncode;
}
}===========================代碼結(jié)束==========================原有UsernamePasswordToken已經(jīng)不滿足我們區(qū)分登錄模式的需求,我們可以繼承UsernamePasswordToken重寫一個(gè)token封裝類CustomToken===========================代碼開始==========================/***自定義令牌**@authorpong*/publicclassCustomTokenextendsUsernamePasswordToken{privateStringloginType;publicCustomToken(){super();}/***@paramloginName用戶名*@parampassword密碼*@paramloginType登錄模式*@paramrememberMe*/publicCustomToken(StringloginName,Stringpassword,StringloginType,booleanrememberMe){super(loginName,password,rememberMe);this.loginType=loginType;}publicStringgetType(){returnloginType;}publicvoidsetType(StringloginType){this.loginType=loginType;}}===========================代碼結(jié)束==========================一個(gè)賬號(hào)密碼登錄的常規(guī)Realm===========================代碼開始==========================/***帳號(hào)密碼登錄*@authorpong*/publicclassNormalRealmextendsAuthorizingRealm{privatestaticfinalLoggerlog=LoggerFactory.getLogger(NormalRealm.class);/***授權(quán)*/@OverrideprotectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionarg0){//授權(quán)業(yè)務(wù)}/***登錄認(rèn)證*/@OverrideprotectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokentoken)throwsAuthenticationException{//認(rèn)證業(yè)務(wù)}}===========================代碼結(jié)束==========================一個(gè)免密登錄的Realm===========================代碼開始==========================/***免密登錄realm*@authorpong*/publicclassFreeRealmextendsAuthorizingRealm{PrivatestaticfinalLoggerlog=LoggerFactory.getLogger(FreeRealm.class);/***授權(quán)*/@OverrideprotectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionarg0){//授權(quán)業(yè)務(wù)}/***免密登錄認(rèn)證*/@OverrideprotectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokentoken)throwsAuthenticationException{StringloginName=(String)token.getPrincipal();SysUseruser=null;if(StringUtils.isNotNull(loginName)){user=userService.selectUserByLoginName(loginName);}SimpleAuthenticationInfoinfo=newSimpleAuthenticationInfo(user,user.getPassword(),getName());returninfo;}}===========================代碼結(jié)束==========================一般Shiro只需要一個(gè)Realm就夠,多Realm存在時(shí),token為了能夠被認(rèn)證通過,會(huì)自動(dòng)遍歷所有Realm,當(dāng)有Realm無法認(rèn)證這個(gè)token的時(shí)候系統(tǒng)就會(huì)異常報(bào)錯(cuò)。因此,要寫一個(gè)選擇器,來讓token找到屬于自己的Realm。Shiro自帶了一個(gè)多Realm選擇器ModularRealmAuthenticator,為滿足項(xiàng)目需求,同樣要進(jìn)行繼承重寫。===========================代碼開始==========================/***用于指定登錄使用對(duì)應(yīng)Realm的控制器**@authorpong*/publicclassUserModularRealmAuthenticatorextendsModularRealmAuthenticator{@OverrideprotectedAuthenticationInfodoAuthenticate(AuthenticationTokenauthenticationToken)throwsAuthenticationException{System.out.println("UserModularRealmAuthenticator:methoddoAuthenticate()execute");//判斷getRealms()是否返回為空assertRealmsConfigured();//強(qiáng)制轉(zhuǎn)換回自定義的CustomizedTokenCustomTokenuserToken=(CustomToken)authenticationToken;//登錄類型StringloginType=userToken.getType();//所有RealmCollection<Realm>realms=getRealms();//登錄類型對(duì)應(yīng)的所有RealmList<Realm>typeRealms=newArrayList<>();for(Realmrealm:realms){if(realm.getName().contains(loginType)){typeRealms.add(realm);}}//判斷是單Realm還是多Realmif(typeRealms.size()==1){System.out.println("doSingleRealmAuthentication()execute");returndoSingleRealmAuthentication(typeRealms.get(0),userToken);}else{System.out.println("doMultiRealmAuthentication()execute");returndoMultiRealmAuthentication(typeRealms,userToken);}}}===========================代碼結(jié)束==========================其中,這段遍歷代碼就是根據(jù)登錄模式分配對(duì)應(yīng)Realm的操作===========================代碼開始==========================List<Realm>typeRealms=newArrayList<>();for(Realmrealm:realms){if(realm.getName().contains(loginType)){typeRealms.add(realm);}}===========================代碼結(jié)束==========================最后,就是在shrioConfig配置上這兩個(gè)自定義Realm和Realm選擇器===========================代碼開始==========================/***系統(tǒng)自帶的Realm管理,主要針對(duì)多realm**/@BeanpublicModularRealmAuthenticatormodularRealmAuthenticator(){//重寫ModularRealmAuthenticatorUserModularRealmAuthenticatormodularRealmAuthenticator=newUserModularRealmAuthenticator();modularRealmAuthenticator.setAuthenticationStrategy(newAtLeastOneSuccessfulStrategy());returnmodularRealmAuthenticator;}/***密碼登錄Realm*/@BeanpublicNormalRealmnormalRealm(){NormalRealmnormalRealm=newNormalRealm();returnnormalRealm;}/***免密登錄Realm*/@BeanpublicFreeRealmfreeRealm(){FreeRealmfreeRealm=newFreeRealm();returnfreeRealm;}/***安全管理器*/@BeanpublicSecurityManagersecurityManager(NormalRealmuserRealm){DefaultWebSecurityManagersecurityManager=newDefaultWebSecurityManager();...//設(shè)置realm.securityManager.setAuthenticator(modularRealmAuthenticator());List<Realm>realms=newArrayList<>();//密碼登錄realmrealms.add(normalRealm(getEhCacheManager()));//免密登錄realmrealms.add(freeRealm(getEhCacheManager()));securityManager.setRealms(realms);...}===========================代碼結(jié)束==========================5.5.2微信掃碼登錄原系統(tǒng)使用的登錄認(rèn)證框架是ApaceShiro,而網(wǎng)上現(xiàn)大部分第三方接微信登錄都是用OAuth2,微信自己也推薦用OAuth2;兩者存在一定差異。但不能為了接一個(gè)登錄,去改變系統(tǒng)的架構(gòu);所以只能轉(zhuǎn)變思路:用戶授權(quán)微信登錄→從微信平臺(tái)拿到用戶標(biāo)識(shí)→如果這個(gè)標(biāo)識(shí)和系統(tǒng)用戶表表示相匹配→給予用戶免密登錄權(quán)限,以此來實(shí)現(xiàn)第三方登錄。參數(shù)是否必須說明appid是應(yīng)用唯一標(biāo)識(shí),在開發(fā)平臺(tái)注冊(cè)審核通過后會(huì)得到redirect_uri是前面多次提到的回調(diào)地址,一般是網(wǎng)站域名response_type是填codescope是網(wǎng)頁應(yīng)用目前僅填寫snsapi_loginstate否用于保持請(qǐng)求和回調(diào)的狀態(tài),授權(quán)請(qǐng)求后原樣帶回給第三方。該參數(shù)可用于防止csrf攻擊(跨站請(qǐng)求偽造攻擊),建議第三方帶上該參數(shù),可設(shè)置為簡單的隨機(jī)數(shù)加session進(jìn)行校驗(yàn)返回說明用戶允許授權(quán)后,將會(huì)重定向到redirect_uri的網(wǎng)址上,并且?guī)蟘ode和state參數(shù):redirect_uri?code=CODE&state=STATE若用戶禁止授權(quán),則重定向后不會(huì)帶上code參數(shù),僅會(huì)帶上state參數(shù):redirect_uri?state=STATE這里又有一個(gè)小坑,很多時(shí)候我們r(jià)edirect_uri填注冊(cè)時(shí)的回調(diào)地址是拿不到code的。具體應(yīng)該是:微信開放平臺(tái)上注冊(cè)時(shí)redirect_uri填網(wǎng)站實(shí)際訪問域名,如獲取code的代碼中redirect_uri填的是域名/方法,如/login具體帶什么方法因項(xiàng)目而異,像我開發(fā)的項(xiàng)目,未登錄訪問肯定會(huì)被定向到登錄頁,所以我?guī)狭?login。接下來就是請(qǐng)求accessToken我們需要用上一步獲取到的code來獲取accessToken/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code 參數(shù)是否必須說明appid是應(yīng)用唯一標(biāo)識(shí),在微信開放平臺(tái)提交應(yīng)用審核通過后獲得secret是應(yīng)用密鑰AppSecret,在微信開放平臺(tái)提交應(yīng)用審核通過后獲得code是填寫第一步獲取的code參數(shù)grant_type是填authorization_code代碼實(shí)現(xiàn)===========================代碼開始==========================/***獲取accessToken*@paramcode*@return*/@OverridepublicMap<String,Object>getAccessToken(Stringcode){Map<String,Object>map=newHashMap<>();try{Stringurl="/sns/oauth2/access_token";Stringparam="appid="+appId+"&secret="+appSecret+"&code="+code+"&grant_type=authorization_code";Stringresult=HttpUtils.sendGet(url,param);JSONObjectjsStr=JSONObject.fromObject(result);StringopenId=jsStr.getString("openid");StringunionId=jsStr.getString("unionid");map.put("openId",openId);map.put("unionId",unionId);}catch(Exceptione){Stringmsg="獲取微信accessToken失敗";Map<String,Object>error=newHashMap<>();error.put("error",msg);returnerror;}returnmap;}===========================代碼結(jié)束==========================通過openId和unionId確定auth表中綁定的用戶id,根據(jù)用戶id從系統(tǒng)用戶表查找對(duì)應(yīng)用戶,如果存在該用戶,則授予免密登錄權(quán)限,至此,接微信第三方登錄基本實(shí)現(xiàn)。===========================代碼開始========================== /***微信掃碼登錄*@paramcode*@return*/@ResponseBody@ApiImplicitParam(paramType="String",value="code",name="code")@PostMapping("/loginByWeChat")publicAjaxResultajaxLoginByWeChat(Stringcode){if(!code.isEmpty()){//獲取accessTokenMap<String,Object>accessTokenMap=weChatLoginService.getAccessToken(code);if(!accessTokenMap.isEmpty()){StringuserOpenId=(String)accessTokenMap.get("openId");StringunionId=(String)accessTokenMap.get("unionId");//根據(jù)openId+unionId確定用戶AuthLoginInfouser=weChatLoginService.selectAuthUser(userOpenId,unionId);if(user!=null){SysUsersysUser=userService.selectUserById(Long.valueOf(user.getUserId()));//免密登錄returnajaxLoginNoPwd(sysUser.getLoginName(),false);}else{redisService.set("openId",userOpenId);redisService.set("unionId",unionId);returnAjaxResult.error("該用戶尚未綁定微信,請(qǐng)輸入帳號(hào)密碼登錄!登錄成功自動(dòng)完成綁定?。?);}}returnAjaxResult.error("登錄失??!");}returnAjaxResult.error("登錄失??!");}===========================代碼結(jié)束==========================對(duì)于系統(tǒng)賬戶與微信的綁定,我的思路是:若是沒有綁定過微信的用戶掃碼登錄,即提示其先賬號(hào)密碼登錄,系統(tǒng)自動(dòng)更新Auth表信息;若未未注冊(cè)用戶,則提示其注冊(cè),注冊(cè)時(shí)自動(dòng)更新Auth表信息。但掃碼登錄只是登錄的一種,更多的時(shí)候用戶只是執(zhí)行簡單的登錄或者注冊(cè);所以我引入了redis服務(wù)。? 當(dāng)一個(gè)用戶是先掃碼再登錄/注冊(cè)的,我會(huì)在redis保存其openId和unionId信息,執(zhí)行登錄/注冊(cè)操作時(shí),先去redis取值,如果存在openId和unionId,說明用戶此時(shí)是在執(zhí)行綁定微信操作,綁定微信操作完成后清除redis中的openId和unionId信息。這樣就可以很簡單的區(qū)分用戶是在進(jìn)行普通的登錄注冊(cè)或者綁定微信的登錄注冊(cè)了。? 怎么確保每一個(gè)掃碼綁定微信的用戶,能從redis拿到屬于自己的openId和unionId呢?可以用第一步請(qǐng)求到的code,開放平臺(tái)給的微信授權(quán)臨時(shí)票據(jù)。結(jié)合code作為對(duì)應(yīng)的openId和unionI在redis的key,可以確保每一個(gè)用戶拿到對(duì)應(yīng)的唯一的openId和unionId;至此,系統(tǒng)對(duì)接微信第三方登錄功能基本完成5.5.3WebSocket的引入SpringBoot對(duì)Websocket的集成程度很高,這里直接上代碼。首先是一個(gè)配置文件。===========================代碼開始==========================@Configuration
publicclasswebSocketConfig{
@Bean
publicServerEndpointExporterserverEndpointExporter(){
returnnewServerEndpointExporter();
}
}===========================代碼結(jié)束==========================WebSocket服務(wù)===========================代碼開始==========================/***websocket服務(wù)*@author:pong*/@ServerEndpoint(value="/chatServer",configurator=HttpSessionConfigurator.class)publicclassChatServer{//靜態(tài)變量,用來記錄當(dāng)前在線連接數(shù)。應(yīng)該把它設(shè)計(jì)成線程安全的。privatestaticintonlineCount=0;//與某個(gè)客戶端的連接會(huì)話,需要通過它來給客戶端發(fā)送數(shù)據(jù)privatestaticCopyOnWriteArraySet<ChatServer>webSocketSet=newCopyOnWriteArraySet<ChatServer>();privateSessionsession;privateStringuserid;privateStringkey;privateHttpSessionhttpSession;privatestaticListlist=newArrayList<>();privatestaticMaproutetab=newHashMap<>();/***連接建立成功調(diào)用的方法*@paramsession可選的參數(shù)。session為與某個(gè)客戶端的連接會(huì)話,需要通過它來給客戶端發(fā)送數(shù)據(jù)*/@OnOpenpublicvoidonOpen(Sessionsession,EndpointConfigconfig){//代碼塊}/***連接關(guān)閉調(diào)用的方法*/@OnClosepublicvoidonClose(){webSocketSet.remove(this);//從set中刪除subOnlineCount();//在線數(shù)減1list.remove(userid);//從在線列表移除這個(gè)用戶routetab.remove(userid);Stringmessage=getMessage("["+userid+"]離開了聊天室,當(dāng)前在線人數(shù)為"+getOnlineCount()+"位","notice",list);broadcast(message);//廣播}/***接收客戶端的message,判斷是否有接收人而選擇進(jìn)行廣播還是指定發(fā)送*@param_message客戶端發(fā)送過來的消息*/@OnMessagepublicvoidonMessage(String_message){Stringdecrypt="";try{//代碼塊}catch(Exceptione){e.printStackTrace();}JSONObjectchat=JSON.parseObject(decrypt);JSONObjectmessage=JSON.parseObject(chat.get("message").toString());if(message.get("to")==null||message.get("to").equals("")){//如果to為空,則廣播;如果不為空,則對(duì)指定的用戶發(fā)送消息broadcast(decrypt);}else{String[]userlist=message.get("to").toString().split(",");singleSend(decrypt,(Session)routetab.get(message.get("from")));//發(fā)送給自己,這個(gè)別忘了for(Stringuser:userlist){if(!user.equals(message.get("from"))){singleSend(decrypt,(Session)routetab.get(user));//分別發(fā)送給每個(gè)指定用戶}}}}/***發(fā)生錯(cuò)誤時(shí)調(diào)用*@paramerror*/@OnErrorpublicvoidonError(Throwableerror){error.printStackTrace();}/***廣播消息*@parammessage*/publicvoidbroadcast(Stringmessage){for(ChatServerchat:webSocketSet){try{chat.session.getBasicRemote().sendText(message);}catch(IOExceptione){e.printStackTrace();continue;}}}/***對(duì)特定用戶發(fā)送消息*@parammessage*@paramsession*/publicvoidsingleSend(Stringmessage,Sessionsession){try{session.getBasicRemote().sendText(message);}catch(IOExceptione){e.printStackTrace();}}/***組裝返回給前臺(tái)的消息*@parammessage交互信息*@paramtype信息類型*@paramlist在線列表*@return*/publicStringgetMessage(Stringmessage,Stringtype,Listlist){代碼塊}publicintgetOnlineCount(){returnonlineCount;}publicvoidaddOnlineCount(){ChatServer.onlineCount++;}publicvoidsubOnlineCount(){ChatServer.onlineCount--;}}===========================代碼結(jié)束==========================5.5.4AES加密實(shí)現(xiàn)AES算法在對(duì)明文加密的時(shí)候,并不是把整個(gè)明文一股腦加密成一整段密文,而是把明文拆分成一個(gè)個(gè)獨(dú)立的明文塊,每一個(gè)明文塊長度128bit進(jìn)行獨(dú)立加密再拼接。如果一個(gè)明文塊長度不夠128bit將會(huì)被填充至128bit。AES的工作模式,體現(xiàn)在把明文塊加密成密文塊的處理過程中。AES加密算法提供了五種不同的工作模式:ECB、CBC、CTR、CFB、OFB。加密解密的模式必須一致!簡單封裝一下代碼:===========================代碼開始==========================/***前端*/varaesUtil={//獲取key,genKey:function(length=16){letrandom="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";letstr="";for(leti=0;i<length;i++){str=str+random.charAt(Math.random()*random.length)}returnstr;},//加密encrypt:function(plaintext,key){if(plaintextinstanceofObject){//JSON.stringifyplaintext=JSON.stringify(plaintext)}letencrypted=CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(plaintext),CryptoJS.enc.Utf8.parse(key),{mode:CryptoJS.mode.ECB,padding:CryptoJS.pad.Pkcs7});returnencrypted.toString();},//解密decrypt:function(ciphertext,key)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 暑期教師培訓(xùn)學(xué)習(xí)計(jì)劃
- 2025年度家庭裝修石材加工及安裝服務(wù)合同范本
- 專業(yè)性合同范本
- 辦公裝飾合同范本
- 買賣攤位合同范本
- 2025年度生態(tài)農(nóng)業(yè)項(xiàng)目土地流轉(zhuǎn)合作合同
- 公司家具購買合同范本
- 會(huì)議營銷分成合同范本
- 關(guān)于解除兼職合同范本
- 法律盡職調(diào)查報(bào)告模板
- 胸腔積液護(hù)理查房-范本模板
- 水土保持方案中沉沙池的布設(shè)技術(shù)
- 安全生產(chǎn)技術(shù)規(guī)范 第25部分:城鎮(zhèn)天然氣經(jīng)營企業(yè)DB50-T 867.25-2021
- 現(xiàn)代企業(yè)管理 (全套完整課件)
- 走進(jìn)本土項(xiàng)目化設(shè)計(jì)-讀《PBL項(xiàng)目化學(xué)習(xí)設(shè)計(jì)》有感
- 《網(wǎng)店運(yùn)營與管理》整本書電子教案全套教學(xué)教案
- 教師信息技術(shù)能力提升培訓(xùn)課件希沃的課件
- 高端公寓住宅項(xiàng)目營銷策劃方案(項(xiàng)目定位 發(fā)展建議)
- 執(zhí)業(yè)獸醫(yī)師聘用協(xié)議(合同)書
- 第1本書出體旅程journeys out of the body精教版2003版
- 2022年肝動(dòng)脈化療栓塞術(shù)(TACE)
評(píng)論
0/150
提交評(píng)論