認證鑒權與API權限控制在微服務架構中的設計與實現(一)

作者: [Aoho’s Blog]

引言: 本文系《認證鑒權與API權限控制在微服務架構中的設計與實現》系列的第一篇,本系列預計四篇文章講解微服務下的認證鑒權與API權限控制的實現。

1. 背景

最近在做權限相關服務的開發,在系統微服務化后,原有的單體應用是基于session的安全權限方式,不能滿足現有的微服務架構的認證與鑒權需求。微服務架構下,一個應用會被拆分成若干個微應用,每個微應用都需要對訪問進行鑒權,每個微應用都需要明確當前訪問用戶以及其權限。尤其當訪問來源不只是瀏覽器,還包括其他服務的調用時,單體應用架構下的鑒權方式就不是特別合適了。在微服務架構下,要考慮外部應用接入的場景、用戶–服務的鑒權、服務–服務的鑒權等多種鑒權場景。

最近在做權限相關服務的開發,在系統微服務化后,原有的單體應用是基于session的安全權限方式,不能滿足現有的微服務架構的認證與鑒權需求。微服務架構下,一個應用會被拆分成若干個微應用,每個微應用都需要對訪問進行鑒權,每個微應用都需要明確當前訪問用戶以及其權限。尤其當訪問來源不只是瀏覽器,還包括其他服務的調用時,單體應用架構下的鑒權方式就不是特別合適了。在微服務架構下,要考慮外部應用接入的場景、用戶–服務的鑒權、服務–服務的鑒權等多種鑒權場景。
比如用戶A訪問User Service,A如果未登錄,則首先需要登錄,請求獲取授權token。獲取token之后,A將攜帶著token去請求訪問某個文件,這樣就需要對A的身份進行校驗,并且A可以訪問該文件。

最近在做權限相關服務的開發,在系統微服務化后,原有的單體應用是基于session的安全權限方式,不能滿足現有的微服務架構的認證與鑒權需求。微服務架構下,一個應用會被拆分成若干個微應用,每個微應用都需要對訪問進行鑒權,每個微應用都需要明確當前訪問用戶以及其權限。尤其當訪問來源不只是瀏覽器,還包括其他服務的調用時,單體應用架構下的鑒權方式就不是特別合適了。在微服務架構下,要考慮外部應用接入的場景、用戶–服務的鑒權、服務–服務的鑒權等多種鑒權場景。
比如用戶A訪問User Service,A如果未登錄,則首先需要登錄,請求獲取授權token。獲取token之后,A將攜帶著token去請求訪問某個文件,這樣就需要對A的身份進行校驗,并且A可以訪問該文件。
為了適應架構的變化、需求的變化,auth權限模塊被單獨出來作為一個基礎的微服務系統,為其他業務service提供服務。

2. 系統架構的變更

單體應用架構到分布式架構,簡化的權限部分變化如下面兩圖所示。

單體應用架構到分布式架構,簡化的權限部分變化如下面兩圖所示。
(1)單體應用簡化版架構圖:

單體應用架構到分布式架構,簡化的權限部分變化如下面兩圖所示。
(1)單體應用簡化版架構圖:
[singl](http://upload-images.jianshu.io/upload_images/2830896-47ef8e53ee297799.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

單體架構

(2)分布式應用簡化版架構圖:

分布式架構

分布式架構,特別是微服務架構的優點是可以清晰的劃分出業務邏輯來,讓每個微服務承擔職責單一的功能,畢竟越簡單的東西越穩定。

但是,微服務也帶來了很多的問題。比如完成一個業務操作,需要跨很多個微服務的調用,那么如何用權限系統去控制用戶對不同微服務的調用,對我們來說是個挑戰。當業務微服務的調用接入權限系統后,不能拖累它們的吞吐量,當權限系統出現問題后,不能阻塞它們的業務調用進度,當然更不能改變業務邏輯。新的業務微服務快速接入權限系統相對容易把控,那么對于公司已有的微服務,如何能不改動它們的架構方式的前提下,快速接入,對我們來說,也是一大挑戰。

3. 技術方案

這主要包括兩方面需求:其一是認證與鑒權,對于請求的用戶身份的授權以及合法性鑒權;其二是API級別的操作權限控制,這個在第一點之后,當鑒定完用戶身份合法之后,對于該用戶的某個具體請求是否具有該操作執行權限進行校驗。

3.1 認證與鑒權

對于第一個需求,筆者調查了一些實現方案:

  1. 分布式Session方案

    分布式Session方案
    分布式會話方案原理主要是將關于用戶認證的信息存儲在共享存儲中,且通常由用戶會話作為 key 來實現的簡單分布式哈希映射。當用戶訪問微服務時,用戶數據可以從共享存儲中獲取。在某些場景下,這種方案很不錯,用戶登錄狀態是不透明的。同時也是一個高可用且可擴展的解決方案。這種方案的缺點在于共享存儲需要一定保護機制,因此需要通過安全鏈接來訪問,這時解決方案的實現就通常具有相當高的復雜性了。

  2. 基于OAuth2 Token方案

    基于OAuth2 Token方案
    隨著 Restful API、微服務的興起,基于Token的認證現在已經越來越普遍。Token和Session ID 不同,并非只是一個 key。Token 一般會包含用戶的相關信息,通過驗證 Token 就可以完成身份校驗。用戶輸入登錄信息,發送到身份認證服務進行認證。AuthorizationServer驗證登錄信息是否正確,返回用戶基礎信息、權限范圍、有效時間等信息,客戶端存儲接口。用戶將 Token 放在 HTTP 請求頭中,發起相關 API 調用。被調用的微服務,驗證Token。ResourceServer返回相關資源和數據。

這邊選用了第二種方案,基于OAuth2 Token認證的好處如下:

  • 服務端無狀態:Token 機制在服務端不需要存儲 session 信息,因為 Token 自身包含了所有用戶的相關信息。
  • 性能較好,因為在驗證 Token 時不用再去訪問數據庫或者遠程服務進行權限校驗,自然可以提升不少性能。
  • 現在很多應用都是同時面向移動端和web端,OAuth2 Token機制可以支持移動設備。
  • OAuth2與Spring Security結合使用,有提供很多開箱即用的功能,大多特性都可以通過配置靈活的變更。
  • 最后一點,也很重要,Spring Security OAuth2的文檔寫得較為詳細。

oauth2根據使用場景不同,分成了4種模式:

  • 授權碼模式(authorization code)
  • 簡化模式(implicit)
  • 密碼模式(resource owner password credentials)
  • 客戶端模式(client credentials)

對于上述oauth2四種模式不熟的同學,可以自行百度oauth2,阮一峰的文章有解釋。常使用的是password模式和client模式。

3.2 操作權限控制

對于第二個需求,筆者主要看了Spring Security和Shiro。

  1. Shiro

    Shiro
    Shiro是一個強大而靈活的開源安全框架,能夠非常清晰的處理認證、授權、管理會話以及密碼加密。Shiro很容易入手,上手快控制粒度可糙可細。自由度高,Shiro既能配合Spring使用也可以單獨使用。

  2. Spring Security

    Spring Security
    Spring社區生態很強大。除了不能脫離Spring,Spring Security具有Shiro所有的功能。而且Spring Security對Oauth、OpenID也有支持,Shiro則需要自己手動實現。Spring Security的權限細粒度更高。但是Spring Security太過復雜。

看了下網上的評論,貌似一邊倒向Shiro。大部分人提出的Spring Security問題就是比較復雜難懂,文檔太長。不管是Shiro還是Spring Security,其實現都是基于過濾器,對于自定義實現過濾器,我想對于很多開發者并不是很難,但是這需要團隊花費時間與封裝可用的jar包出來,對于后期維護和升級,以及功能的擴展。很多中小型公司并不一定具有這樣的時間和人力投入這件事。筆者綜合評估了下復雜性與所要實現的權限需求,以及上一個需求調研的結果,既然Spring Security功能足夠強大且穩定,最終選擇了Spring Security。

4. 系統架構

4.1 組件

Auth系統的最終使用組件如下:

OAuth2.0 JWT Token
Spring Security
Spring boot

4.2 步驟

主要步驟為:

  • 配置資源服務器和認證服務器
  • 配置Spring Security

上述步驟比較籠統,對于前面小節提到的需求,屬于Auth系統的主要內容,筆者后面會另寫文章對應講解。

4.3 endpoint

提供的endpoint:

/oauth/token?grant_type=password #請求授權token/oauth/token?grant_type=refresh_token #刷新token/oauth/check_token #校驗token/logout #注銷token及權限相關信息

4.4 maven依賴

主要的jar包,pom.xml文件如下:

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>2.2.0</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId><version>1.2.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId><version>1.2.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jersey</artifactId><version>1.5.3.RELEASE</version></dependency>

4.5 AuthorizationServer配置文件

AuthorizationServer配置主要是覆寫如下的三個方法,分別針對endpoints、clients、security配置。

@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//配置客戶端認證clients.withClientDetails(clientDetailsService(dataSource));}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { //配置token的數據源、自定義的tokenServices等信息endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore(dataSource)).tokenServices(authorizationServerTokenServices()).accessTokenConverter(accessTokenConverter()).exceptionTranslator(webResponseExceptionTranslator);}

4.6 ResourceServer配置

資源服務器的配置,覆寫了默認的配置。為了支持logout,這邊自定義了一個CustomLogoutHandler并且將logoutSuccessHandler指定為返回http狀態的HttpStatusReturningLogoutSuccessHandler

@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().requestMatchers().antMatchers("/**").and().authorizeRequests().antMatchers("/**").permitAll().anyRequest().authenticated().and().logout().logoutUrl("/logout").clearAuthentication(true).logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()).addLogoutHandler(customLogoutHandler());

4.7 執行endpoint

  1. 首先執行獲取授權的endpoint。
method: post 
url: http://localhost:12000/oauth/token?grant_type=password
header:
{Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,Content-Type: application/x-www-form-urlencoded
}
body:
{username: keets,password: ***
}

上述構造了一個post請求,具體請求寫得很詳細。username和password是客戶端提供給服務器進行校驗用戶身份信息。header里面的Authorization是存放的clientId和clientSecret經過編碼的字符串。

上述構造了一個post請求,具體請求寫得很詳細。username和password是客戶端提供給服務器進行校驗用戶身份信息。header里面的Authorization是存放的clientId和clientSecret經過編碼的字符串。
返回結果如下:

{   "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsImV4cCI6MTUwODQ0Nzc1NiwidXNlcl9uYW1lIjoia2VldHMiLCJqdGkiOiJiYWQ3MmIxOS1kOWYzLTQ5MDItYWZmYS0wNDMwZTdkYjc5ZWQiLCJjbGllbnRfaWQiOiJmcm9udGVuZCIsInNjb3BlIjpbImFsbCJdfQ.5ZNVN8TLavgpWy8KZQKArcbj7ItJLLaY1zBRaAgMjdo",   "token_type": "bearer","refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsInVzZXJfbmFtZSI6ImtlZXRzIiwic2NvcGUiOlsiYWxsIl0sImF0aSI6ImJhZDcyYjE5LWQ5ZjMtNDkwMi1hZmZhLTA0MzBlN2RiNzllZCIsImV4cCI6MTUxMDk5NjU1NiwianRpIjoiYWE0MWY1MjctODE3YS00N2UyLWFhOTgtZjNlMDZmNmY0NTZlIiwiY2xpZW50X2lkIjoiZnJvbnRlbmQifQ.mICT1-lxOAqOU9M-Ud7wZBb4tTux6OQWouQJ2nn1DeE","expires_in": 43195,"scope": "all","X-KEETS-UserId": "d6448c24-3c4c-4b80-8372-c2d61868f8c6","jti": "bad72b19-d9f3-4902-affa-0430e7db79ed","X-KEETS-ClientId": "frontend"
}

可以看到在用戶名密碼通過校驗后,客戶端收到了授權服務器的response,主要包括access*?token、refresh*?token。并且表明token的類型為bearer,過期時間expires_in。筆者在jwt token中加入了自定義的info為UserId和ClientId。

2.鑒權的endpoint

method: post 
url: http://localhost:12000/oauth/check_token
header:
{Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,Content-Type: application/x-www-form-urlencoded
}
body:
{token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsImV4cCI6MTUwODQ0Nzc1NiwidXNlcl9uYW1lIjoia2VldHMiLCJqdGkiOiJiYWQ3MmIxOS1kOWYzLTQ5MDItYWZmYS0wNDMwZTdkYjc5ZWQiLCJjbGllbnRfaWQiOiJmcm9udGVuZCIsInNjb3BlIjpbImFsbCJdfQ.5ZNVN8TLavgpWy8KZQKArcbj7ItJLLaY1zBRaAgMjdo
}

上面即為check_token請求的詳細信息。需要注意的是,筆者將剛剛授權的token放在了body里面,這邊可以有多種方法,此處不擴展。

{"X-KEETS-UserId": "d6448c24-3c4c-4b80-8372-c2d61868f8c6","user_name": "keets","scope": ["all"],"active": true,"exp": 1508447756,"X-KEETS-ClientId": "frontend","jti": "bad72b19-d9f3-4902-affa-0430e7db79ed","client_id": "frontend"
}

校驗token合法后,返回的response如上所示。在response中也是展示了相應的token中的基本信息。

3.刷新token

3.刷新token
由于token的時效一般不會很長,而refresh*?token一般周期會很長,為了不影響用戶的體驗,可以使用refresh*?token去動態的刷新token。

method: post 
url: http://localhost:12000/oauth/token?grant_type=refresh_token&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsInVzZXJfbmFtZSI6ImtlZXRzIiwic2NvcGUiOlsiYWxsIl0sImF0aSI6ImJhZDcyYjE5LWQ5ZjMtNDkwMi1hZmZhLTA0MzBlN2RiNzllZCIsImV4cCI6MTUxMDk5NjU1NiwianRpIjoiYWE0MWY1MjctODE3YS00N2UyLWFhOTgtZjNlMDZmNmY0NTZlIiwiY2xpZW50X2lkIjoiZnJvbnRlbmQifQ.mICT1-lxOAqOU9M-Ud7wZBb4tTux6OQWouQJ2nn1DeE
header:
{Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=
}

其response和/oauth/token得到正常的相應是一樣的,此處不再列出。

4.注銷token

method: get
url: http://localhost:9000/logout
header:
{Authorization: bearereyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MDgzMzkwNTQsIlgtU0lNVS1Vc2VySWQiOiIwOGFhMTYxYi1lYjI3LTQ2NjAtYjA1MC1lMDc5YTJiODBhODMiLCJ1c2VyX25hbWUiOiJrZWV0cyIsImp0aSI6IjJhNTQ4NjY2LTRjNzEtNGEzNi1hZmY0LTMwZTI1Mjc0ZjQxZSIsImNsaWVudF9pZCI6ImZyb250ZW5kIiwic2NvcGUiOlsibWVua29yIl19.rA-U2iXnjH0AdPaGuvSEJH3bTth6AT3oQrGsKIams30
}

注銷成功則會返回200,注銷端點主要是將token和SecurityContextHolder進行清空。

5. 總結

本文是《認證鑒權與API權限控制在微服務架構中的設計與實現》系列文章的總述,從遇到的問題著手,介紹了項目的背景。通過調研現有的技術,并結合當前項目的實際,確定了技術選型。最后對于系統的最終的實現進行展示。后面將從實現的細節,講解本系統的實現。敬請期待后續文章。


參考

  1. 理解OAuth 2.0
  2. 微服務API級權限的技術架構
  3. 微服務架構下的安全認證與鑒權

我的官網
我的博客

我的官網http://guan2ye.com
我的CSDN地址http://blog.csdn.net/chenjianandiyi
我的簡書地址http://www.jianshu.com/u/9b5d1921ce34
我的githubhttps://github.com/javanan
我的碼云地址https://gitee.com/jamen/
阿里云優惠券https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=vf2b5zld&utm_source=vf2b5zld

阿里云教程系列網站http://aliyun.guan2ye.com

1.png

我的開源項目spring boot 搭建的一個企業級快速開發腳手架

1.jpg

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/391954.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391954.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391954.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mac下完全卸載程序的方法

在國外網上看到的&#xff0c;覺得很好&#xff0c;不僅可以長卸載的知識&#xff0c;還對mac系統有更深的認識。比如偏好設置文件&#xff0c;我以前設置一個程序壞了&#xff0c;打不開了&#xff0c;怎么重裝都打不開&#xff0c;后來才知道系統還保留著原來的偏好設置文件。…

機器學習集群_機器學習中的多合一集群技術在無監督學習中應該了解

機器學習集群Clustering algorithms are a powerful technique for machine learning on unsupervised data. The most common algorithms in machine learning are hierarchical clustering and K-Means clustering. These two algorithms are incredibly powerful when appli…

自考本科計算機要學什么,計算機自考本科需要考哪些科目

高科技發展時代&#xff0c;怎離得開計算機技術&#xff1f;小學生都要學編程了&#xff0c;未來趨勢一目了然&#xff0c;所以如今在考慮提升學歷的社會成人&#xff0c;多半也青睞于計算機專業&#xff0c;那么計算機自考本科需要考哪些科目&#xff1f;難不難&#xff1f;自…

審查指南 最新版本_代碼審查-最終指南

審查指南 最新版本by Assaf Elovic通過阿薩夫埃洛維奇 代碼審查-最終指南 (Code Review — The Ultimate Guide) 構建團隊代碼審查流程的終極指南 (The ultimate guide for building your team’s code review process) After conducting hundreds of code reviews, leading R…

非對稱加密

2019獨角獸企業重金招聘Python工程師標準>>> 概念 非對稱加密算法需要兩個密鑰&#xff1a;公鑰&#xff08;publickey&#xff09;和私鑰&#xff08;privatekey&#xff09;。公鑰與私鑰是一對&#xff0c;如果用公鑰對數據進行加密&#xff0c;只有用對應的私…

管理Sass項目文件結構

http://www.w3cplus.com/preprocessor/architecture-sass-project.html 編輯推薦&#xff1a; 掘金是一個高質量的技術社區&#xff0c;從 CSS 到 Vue.js&#xff0c;性能優化到開源類庫&#xff0c;讓你不錯過前端開發的每一個技術干貨。 點擊鏈接查看最新前端內容&#xff0c…

Spring—注解開發

Spring原始注解 Spring是輕代碼而重配置的框架&#xff0c;配置比較繁重&#xff0c;影響開發效率&#xff0c;所以注解開發是一種趨勢&#xff0c;注解代替xml配置文 件可以簡化配置&#xff0c;提高開發效率。 Component 使用在類上用于實例化BeanController 使用在web層類…

政府公開數據可視化_公開演講如何幫助您設計更好的數據可視化

政府公開數據可視化What do good speeches and good data visualisation have in common? More than you may think.好的演講和好的數據可視化有什么共同點&#xff1f; 超出您的想象。 Aristotle — the founding father of all things public speaking — believed that th…

C++字符串完全指引之一 —— Win32 字符編碼 (轉載)

C字符串完全指引之一 —— Win32 字符編碼原著&#xff1a;Michael Dunn翻譯&#xff1a;Chengjie Sun 原文出處&#xff1a;CodeProject&#xff1a;The Complete Guide to C Strings, Part I 引言  毫無疑問&#xff0c;我們都看到過像 TCHAR, std::string, BSTR 等各種各樣…

網絡計算機無法訪問 請檢查,局域網電腦無法訪問,請檢查來賓訪問帳號是否開通...

局域網電腦無法訪問&#xff0c;有時候并不是由于網絡故障引起的&#xff0c;而是因為自身電腦的一些設置問題&#xff0c;例如之前談過的網絡參數設置不對造成局域網電腦無法訪問。今天分析另一個電腦設置的因素&#xff0c;它也會導致局域網電腦無法訪問&#xff0c;那就是賓…

unity中創建游戲場景_在Unity中創建Beat Em Up游戲

unity中創建游戲場景Learn how to use Unity to create a 3D Beat Em Up game in this full tutorial from Awesome Tuts. 在Awesome Tuts的完整教程中&#xff0c;了解如何使用Unity來創建3D Beat Em Up游戲。 This tutorial covers everything you need to know to make a …

雷軍的金山云D輪獲3億美元!投后估值達19億美金

12月12日&#xff0c;雷軍旗下金山云宣布D輪完成3億美元融資&#xff0c;金額為云行業單輪融資最高。至此金山云投后估值達到19億美元&#xff0c;成為國內估值最高的獨立云服務商。金山集團相關公告顯示&#xff0c;金山云在本輪融資中總計發行3.535億股D系列優先股。驪悅投資…

轉:利用深度學習方法進行情感分析以及在海航輿情云平臺的實踐

http://geek.csdn.net/news/detail/139152 本文主要為大家介紹深度學習算法在自然語言處理任務中的應用——包括算法的原理是什么&#xff0c;相比于其他算法它具有什么優勢&#xff0c;以及如何使用深度學習算法進行情感分析。 原理解析 在講算法之前&#xff0c;我們需要先剖…

消費者行為分析_消費者行為分析-是否點擊廣告?

消費者行為分析什么是消費者行為&#xff1f; (What is Consumer Behavior?) consumer behavior is the study of individuals, groups, or organizations and all the activities associated with the purchase, use, and disposal of goods and services, and how the consu…

Spring—集成Junit

Spring集成Junit步驟 ①導入spring集成Junit的坐標 ②使用Runwith注解替換原來的運行期 ③使用ContextCon?guration指定配置文件或配置類 ④使用Autowired注入需要測試的對象 ⑤創建測試方法進行測試 ①導入spring集成Junit的坐標 <dependency> <groupId>org.s…

計算機的微程序存放在dram,計算機組成與結構

計算機組成與結構A/B卷填空1. 原碼一位乘法中&#xff0c;符號位與數值位(分開計算)&#xff0c;運算結果的符號位等于(相乘兩數符號位的異或值)。2. 微程序&#xff0c;微指令只存放在只讀存儲器中。3. 輔助磁道被分為若干個扇區4. 總線數據傳輸方式&#xff1a;_串行_,_并行_…

python算法面試_求職面試的Python算法

python算法面試During software job interviews, candidates often have to solve algorithm challenges. In this video from CupOfCode01, you will learn about common algorithm concepts in Python and how to solve algorithm challenges you may encounter in an interv…

vue實用難點講解

此篇文章是我基于研究vue文檔三遍的基礎上&#xff0c;覺得還有點難理解或者難記的知識點總結 列表渲染 1.渲染組件必須加key&#xff0c;并且屬性是手動傳遞給組件的<my-componentv-for"(item, index) in items"v-bind:item"item"v-bind:index"in…

leetcode 1208. 盡可能使字符串相等(滑動窗口)

給你兩個長度相同的字符串&#xff0c;s 和 t。 將 s 中的第 i 個字符變到 t 中的第 i 個字符需要 |s[i] - t[i]| 的開銷&#xff08;開銷可能為 0&#xff09;&#xff0c;也就是兩個字符的 ASCII 碼值的差的絕對值。 用于變更字符串的最大預算是 maxCost。在轉化字符串時&a…

魅族mx5游戲模式小熊貓_您不知道的5大熊貓技巧

魅族mx5游戲模式小熊貓重點 (Top highlight)I’ve been using pandas for years and each time I feel I am typing too much, I google it and I usually find a new pandas trick! I learned about these functions recently and I deem them essential because of ease of u…