最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

學習記錄之Spring Security框架

2022-07-13 00:27 作者:星月襲空  | 我要投稿

SECURITY

Spring Security框架

Spring Security框架主要解決了**認證**與**授權**的相關問題。

添加依賴

?在Spring Boot項目中,需要使用Spring Security時,需要添加spring-boot-starter-security依賴。

當項目中添加此依賴后,默認會執(zhí)行一系列的自動配置,將:當前項目中所有的訪問,都是必須先登錄才允許的。未登錄時,將自動重定向到 `/login`,當登錄成功后,將自動重定向到此前訪問的頁面,或主頁

? - 訪問 /logout可以退出登錄

? - 如果希望某些路徑不需要登錄就可以訪問,可以自定義Spring Security的配置類,將這些路徑配置為“白名單”

- 啟動項目的過程中,會生成隨機的臨時密碼,用戶名為`user`

密碼加密

在開發(fā)實踐中,所有的用戶密碼都**必須**加密之后,再存儲到數據庫中。

用戶的原始密碼(例如`1234`)通常稱之為**原文**或**明文**,加密后得到的結果(例如`lkjfadshfdslafndshdsfaj`)通常稱之為**密文**。

在處理加密時,通常應該選取**消息摘要算法**對用戶的密碼進行處理!

注意:不可以使用加密算法對密碼進行加密并存儲,通常,加密算法是用于保障傳輸過程的安全的!

消息摘要算法是**不可逆**的算法,是適合對密碼進行加密的!

消息摘要算法的主要特點有:

- 同一種算法,無論消息長度多少,摘要的長度是固定的

- 當消息相同時,摘要必然相同

- 當消息不同時,摘要理論上不會相同(有概率是相同的)

- 消息的長度是無限的,摘要的長度是有限且固定的

需要注意:理論上有n種不同的消息對應同一個摘要,但是,出現這樣的現象的概率極低!

典型的消息摘要算法有:

- MD系列(Message Digest):MD2 / MD4` / MD5

- MD系列的全部是128位算法

- SHA家族(Secure Hash Algorithm):SHA-1?/ SHA-256 / SHA-384?/ SHA-512

?- SHA-1是160位算法,其它則是與算法名稱對應,例如 SHA-256 就是256位算法

- SM3(國家加密算法)

?- SM3是256位算法

在Spring Boot中,spring-boot-starter 依賴項就包含 DigestUtils 工具類,可以簡便的實現MD5算法的處理,例如:

如果想要使用其它消息摘要算法,可以自行在項目中添加 commons-codec 依賴項,此依賴中也有一個名為 DigestUtils 的工具類,提供了多種算法的API。

由于消息算法的特點包括“消息相同,摘要必然相同”,所以,在互聯網上有一些平臺記錄了消息與摘要的對應關系,記錄在數據庫,可以根據摘要進行反向查詢,從而得知摘要對應的消息!但是,由于這些平臺能夠記錄的對應關系非常有限,可以使用更復雜的消息,大概率是沒有被這些平臺收錄的,則不會被這些平臺反向查詢出原消息!

換言之,只要原始密碼足夠復雜,則不會被這些平臺“破解”。

但是,某些場景中并不支持使用復雜的消息(密碼),也有些用戶不愿意使用復雜的原始密碼,則很容易被窮舉出消息與摘要的對應列表,為解決此問題,應該在加密過程中使用“鹽”,鹽的本質就是一個字符串,其作用是使得被運算數據變得更加復雜,例如:


而鹽值的具體值并沒有明確的要求,包括其使用方式也沒有明確的要求!

另外,還可以嘗試多重加密,即循環(huán)調用以上算法。

所以,為了提高密碼的安全性:

-強制要求使用強度更高的密碼

- 加鹽

- 多重加密

- 使用更安全的算法

- 綜合使用以上做法

關于鹽的補充:通常,可以使用隨機的鹽值,則即使完全相同的原始密碼,得到的加密結果也完全不同,例如:

需要注意的是,一旦使用隨機的鹽值,則必須將此隨機的鹽值記錄下來**(可以在添加數據時,在數據表中使用專門的字段進行記錄,或者,將鹽址和加密結果合并成1個字符串作為記錄下來的密碼),否則,在后續(xù)的驗證密碼時,將無法運算得到匹配的結果!

使用示例:

rawPassword = 123456

salt = 4da1ba18-e9c5-4adc-bc0e-3768aca841ad

encodedPassword = ef3bcab34967ab87d9a3002366439898

得到最終密碼(鹽值拼接密文):

4da1ba18-e9c5-4adc-bc0e-3768aca841adef3bcab34967ab87d9a3002366439898

當使用了Spring Security框架后,此框架中還包含了 BCryptPasswordEncoder 類,此類可以使用BCrypt算法對密碼進行處理,調用此類對象的 encode() 方法即可實現加密,調用 matches() 方法就可以實現將原文和密文進行對比?。ㄟ@2個方法都是在 PasswordEncoder 接口中定義的)

在Spring Security中放行某些請求

默認情況下,Spring Security要求所有請求都是必須登錄后才可以訪問的,當需要放行某些請求時,可以將這些請求路徑配置為“白名單”。

需要自定義配置類,繼承自 WebSecurityConfigurerAdapter 類,重寫其中的 configurer(HttpSecurity)方法:

使用數據庫中的賬號實現登錄

在Spring Security,使用默認的登錄時(默認存在的`/login`頁面),默認情況下使用 user 作為用戶名,使用啟動時生成的臨時密碼。在處理過程中,也可以使其使用數據庫中的賬號進行登錄,Spring Security 會自動獲取在輸入框中輸入的用戶名、密碼,然后,會自動調用 UserDetailsService 接口類型對象的 UserDetails loadByUsername(String username) 方法,并獲取返回的 UserDetails 對象,此對象中應該包含密碼的密文值,接下來,Spring Security會自動將登錄界面中獲取的密碼原文進行加密,并與 UserDetails 中的密文進行對比,以判斷是否可以成功登錄。

在測試之前,應該先禁用(注釋掉相關代碼)Spring Security中的 configurer(HttpSecurity) 方法,否則將不會顯示 `/login` 頁面。

接下來,在項目的根包下自定義類 security.UserDetailsServiceImpl 類,實現 UserDetailsService 接口,并重寫接口中的 loadByUsername() 方法:

一旦編寫了 UserDetailsService 接口的實現類,并將此類由Spring創(chuàng)建對象,則Spring Security會自動裝配此類的對象,在后續(xù)啟動項目時,將不再生成默認的隨機密碼,且默認的用戶名 user 將不再可用。

可以在此方法中測試返回某個賬號信息,例如:

如果此時重啟項目,并通過 `/login` 測試登錄:

- 當用戶名不是 zhangsan 時,瀏覽器將提示 UserDetailsService returned null ,且IntelliJ IDEA控制臺會有異常信息

- 當用戶名是 zhangsan? 但密碼不是 123456 時,在瀏覽器將提示“用戶名或密碼錯”

- 當用戶名是 zhangsan? 且密碼是 123456 時,將登錄成功(登錄后的跳轉可能404)

如果要改為通過數據庫中的賬號來實現登錄,則在以上代碼中,替換為“根據用戶名查詢管理員信息,如果存在此用戶名對應的數據,則將查詢到的管理員信息封裝到 UserDetails 中并返回”即可。

所以,接下來需要執(zhí)行的任務:

- 在根包下創(chuàng)建 pojo.vo.AdminLoginVO 類,此類中至少包括:用戶名、密碼

- 在 AdminMapper 接口中添加抽象方法 AdminLoginVO getByUsername(String username);

- 在 AdminMapper.xml 中配置以上抽象方法映射的SQL

mysql

??? select username, password from ams_admin where username=?

在 AdminMapperTests 中進行測試

- 在 UserDetailsServiceImpl 中,自動裝配 AdminMapper 對象,然后調用以上查詢功能,并將查詢到的結果中的信息封裝到返回的 UserDetails 中去,如果未查詢到有效記錄,可以直接返回 null 。

自定義處理登錄的流程

默認情況下,Spring Security有默認的登錄頁,輸入用戶名、密碼后,是由Spring Security自動接收登錄請求,然后進行處理的,如果登錄成功,會自動跳轉到此前訪問的頁面,如果登錄失敗,會將錯誤信息提示到默認的登錄頁上。

以上這套流程不適用于開發(fā)實踐,因為:

- 這不是前后端分離的做法(服務器端處理了登錄后,不響應JSON結果)

- 不便于處理細節(jié),例如使用Validation框架驗證請求參數的格式

要解決此問題,應該:像開發(fā)其它數據處理流程一樣的做法,只不過,在自定義的Service實現過程中,通過Spring Security的機制來驗證用戶名和密碼即可。

首先,需要使得控制器可以接收客戶端提交的登錄請求,需要:

- 在根包下創(chuàng)建`pojo.dto.AdminLoginDTO`類,在此類中封裝登錄請求的相關參數,例如:用戶名,密碼

- 在`AdminController`中添加處理登錄請求的方法:

完成后,可以Knife4j中測試訪問,且響應結果永遠是成功(目前還沒有真正的實現登錄)然后,需要在Service中準備處理登錄,需要:

在`IAdminService`中聲明:`void login(AdminLoginDTO adminLoginDTO);`

- 在`AdminServiceImpl`中重寫以上方法,實現細節(jié)可暫時留空

- 在`AdminController`處理登錄時調用Service組件的此方法

關于在Service中處理登錄的細節(jié),應該使用Spring Security中的`AuthenticationManager`對象來執(zhí)行Spring Security的認證過程(后續(xù)保存用戶信息、授權訪問等都需要)。

?

如果需要得到`AuthenticationManager`,需要在Spring Security的配置類(自定義的`SecurityConfiguration`類)中重寫`authenticationManager()`方法,此方法可以返回`AuthenticationManager`對象,則在重寫在方法上添加`@Bean`注解,可以使得Spring會自動調用此方法,并將返回結果保存在Spring容器中:

然后,回到業(yè)務實現類中,自動裝配`AuthenticationManager`對象,在具體實現時,調用此對象的`authenticate()`方法,即可實現Spring Security的認證,此方法的參數可使用`UsernamePasswordAuthenticationToken`來封裝用戶名和密碼:

以上代碼的執(zhí)行流程大致是:

請求 ==> Controller ==> Service ==> AuthenticationManager ==> UserDetailsServiceImpl ==> Mapper

關于Session

HTTP協議是**無狀態(tài)**的協議,從協議本身來說,通信過程中并不會記錄用戶的相關信息,如果某用戶第1次訪問了服務器后,第2次再次訪問時,服務器并不會知道這是與第1次訪問時是同一個用戶!

在開發(fā)實踐時,需要明確用戶的身份,所以,各編程語言都提供了基于Session的處理機制,Session是服務器端程序維護的一個類似`Map`的數據,每個客戶端都有一個唯一的Key對應到此處的某個值!所以,各個客戶端的訪問時,都可以向自己對應的Session數據中存入數據,后續(xù),也可以取出之前存入的數據,例如,可以在登錄成功后將用戶的id存入到Session中,后續(xù),就可以根據“Session中有沒有此id”來判斷用戶是否登錄了,并根據存入的用戶id來識別用戶的身份。

在Session的具體使用過程中,當某個客戶端第1次向服務器端發(fā)出請求時,并沒有所謂的`Map`的Key,則服務器會會自動生成一個Key響應到客戶端去,客戶端會自動將此Key保存下來,并在后續(xù)每次發(fā)出請求時都自動攜帶這個Key!在此過程中,客戶端還會使用Cookie技術將Key保存在客戶端!

Session中的Key本身上都是UUID值,本身并沒有具體的信息含義,只是具有唯一性,使得各客戶端訪問服務器端的Session時不會發(fā)生沖突。

目前,并不推薦使用Session技術來處理識別用戶的身份,因為在集群架構中,同一個用戶的多次請求可能是由集群中不同的服務器進行處理,而Session是存儲在服務器內存中的數據,直接使用的話,就會無法識別用戶的身份!

關于Token

Token可以稱之為“票據”、“令牌”,其最大的特點是類似于Session的Key這樣的數據中是體現信息含義的!相當于“火車票”,票上是可以體現一些數據的,服務器就相當于“車站”,不同的車站都有相同的驗票機制,能夠識別“火車票”的真?zhèn)危闹蝎@取某些信息。

關于JWT

JWT = Json Web Token,相比普通Token,它使用JSON封裝更多的信息含義。

為了保證JWT數據在網絡上傳輸時的安全,JWT本身是一組加密后的數據,通常,有相關的工具包來負責生成JWT并解析JWT中的數據。

可以選擇使用`jjwt`工具包來實現,在項目中,添加依賴項:

測試**生成JWT**和**解析JWT**

生成的JWT:

eyJ0eXAiOiJqd3QiLCJhbGciOiJIUzI1NiJ.eyJuYW1lIjoi5YiY6ICB5biIIiwiaWQiOjk1MjcsImV4cCI6MTY1NzYxOTY2Nn0.kDW_hgQKbBb01WA5kQeMaxY8Fc_H2Yao2DdFABlbuiw

學習記錄之Spring Security框架的評論 (共 條)

分享到微博請遵守國家法律
乌恰县| 庆云县| 嘉黎县| 留坝县| 眉山市| 榆社县| 桦川县| 五家渠市| 长垣县| 华坪县| 璧山县| 邵阳市| 镇原县| 南江县| 固始县| 新乡县| 德格县| 黄浦区| 增城市| 九龙坡区| 怀远县| 松溪县| 芦溪县| 吉安市| 龙泉市| 利津县| 柘荣县| 东阿县| 来凤县| 安远县| 新建县| 凤阳县| 额济纳旗| 育儿| 达州市| 苏州市| 喀喇| 湖州市| 临西县| 雷州市| 辽阳县|