SpringSecurity是專門針對基於Spring項目的安全框架,充分利用了依賴注入和AOP來實現安全管控。在不少大型企業級系統中權限是最核心的部分,一個系統的好與壞全都在於權限管控是否靈活,是否顆粒化。在早期的SpringSecurity版本中咱們須要大量的xml來進行配置,而基於SpringBoot整合SpringSecurity框架相對而言簡直是重生了,簡單到難以想象的地步。git
SpringSecurity框架有兩個概念認證和受權,認證能夠訪問系統的用戶,而受權則是用戶能夠訪問的資源,下面咱們來簡單講解下SpringBoot對SpringSecurity安全框架的支持。spring
在SpringBoot項目中使用SpringSecurity安全框架實現用戶認證以及受權訪問。數據庫
咱們使用IntelliJ IDEA工具建立一個SpringBoot項目,預先加入JPA、Security、Druid、MySQL等依賴,項目結構以下圖1所示:緩存
咱們下面先來配置數據庫訪問的配置,將咱們以前章節(第十三章:SpringBoot實戰SpringDataJPA)的application.yml配置文件複製到本章項目resources目錄下,以下圖2所示:安全
數據庫鏈接配置完成後,咱們開始建立本章須要用到的三張表,用戶表、角色表、用戶角色關聯表,一個用戶存在多個角色!用戶表結構圖下圖3所示:app
咱們用戶表結構僅有三個字段,這裏只是爲了演示咱們的安全框架,因此不作太過詳細。下面是咱們的角色信息表結構以下圖4所示:框架
由於咱們一個用戶存在多個角色,一個角色又能夠應用到多個用戶上,因此咱們採用的關聯表的方式進行配置關係,用戶角色關聯表結構以下圖5所示:jsp
下面咱們根據用戶信息表以及角色信息表建立對應的實體,以下圖六、圖7所示:spring-boot
能夠看到咱們的UserEntity實現了UserDetails接口,UserDetails是SpringSecurity驗證框架內部提供的用戶驗證接口(咱們下面須要用到UserEntity來完成自定義用戶認證功能),咱們須要實現getAuthorities方法內容,將咱們定義的角色列表添加到受權的列表內。工具
能夠看到咱們的用戶實體內添加了對角色的列表支持,並添加了@ManyToMany的關係註解。咱們查詢用戶時SpringDataJPA會自動查詢處關聯表user_roles對應用戶的角色列表放置到名叫roles的List集合內。
咱們對用戶表、角色表、關聯表添加幾條對應的數據,SQL腳本以下圖8所示:
初始化的SQL腳本已經添加到本章的resources目錄下,本章結束爲止會有源碼下載地址。
根據建立的UserEntity實體來建立UserJPA接口並繼承JPARepository接口,UserJPA內添加一個根據用戶名查詢的方法,以下圖9所示:
咱們能夠看到我在圖9的UserJPA接口內添加了一個findByUsername方法,這個方法實際上是SpringDataJPA的一個規則,咱們這樣寫JPA就會認爲咱們要根據username這個字段去查詢,並自動使用參數索引爲0的值(有關SpringDataJPA方法查詢後期會在SpringDataJPA 核心技術內體現)。
咱們上面的配置差很少已經完成,下面咱們實現SpringSecurity內的UserDetailsService接口來完成自定義查詢用戶的邏輯,以下圖10所示:
能夠看到上圖10內的定義,實現UserDetailsService接口須要完成loanUserByUsername重寫,咱們使用UserJPA內的findByUsername方法從數據庫中讀取用戶,並將用戶做爲方法的返回值。
自定義用戶認證已經編寫完成,下面咱們須要配置SpringBoot項目支持SpringSecurity安全框架,具體配置代碼以下圖11所示:
能夠看到咱們上圖11配置了全部請求都必須登陸訪問,第一句咱們僅用了csrd,在springSecurity4.0後,默認開啓了CSRD攔截,若是須要配置請在form表單添加以下圖12配置:
咱們這裏配置了登陸頁面127.0.0.1:8080/login請求地址以及登陸錯誤頁面/login?error不被SpringSecurity攔截。下面咱們來編寫登陸的JSP頁面,咱們以前構建項目的時候並無添加JSP的依賴,下面咱們修改pom.xml添加JSP依賴,以下圖13所示:
咱們修改application.yml配置文件添加JSP的頁面配置,以下圖14所示:
好了,下面咱們簡單的建立一個login.jsp頁面,頁面裏面添加一個簡單的表單提交,咱們的表單提交地址這裏要注意了,SpringSecurity內部已經給咱們定義好了,在4.0版本以後登陸地址都是/login,固然這個/login並非咱們上面配置的loginPage地址。這個地址若是直接訪問是訪問不到的。必須採用Post形式訪問,login.jsp頁面內容以下圖15所示:
咱們來配置一個簡單的SpringBoot內的MVC控制器跳轉,下面咱們添加一個名叫MVCConfig配置類繼承WebMvcConfigurerAdapter類,重寫addViewControllers()方法添加路徑訪問,能夠經過Get形式的/login訪問到咱們的login.jsp,代碼以下圖16所示:
上面有關SpringSecurity配置都已經完成,接下來咱們添加一個IndexController來測試咱們的SprinySecurity框架是否已經生效,咱們上面已經配置了,若是在不登錄的狀態下只有/login是能夠訪問的,因此咱們直接訪問/index是不可行的。SpringSecurity會直接給咱們重定向到咱們配置的loginPage,IndexController代碼以下圖17所示:
下面咱們來啓動項目,先來訪問/index查看界面效果,以下圖18所示:
正如咱們所說的,當咱們在沒有登陸的狀態下訪問/index時,會直接被安全框架重定向到登陸頁面,那麼咱們登陸後,再來訪問/index並查看界面輸出,以下圖19所示:
能夠看到界面的效果,咱們已經能夠正確的訪問到index路徑所返回的數據,證實了咱們的安全框架已經生效了。
咱們在文章開始的部分已經建立了角色表,咱們下面就要根據角色,在用戶登陸成功後顯示不一樣的內容,在這以前咱們須要添加SpringSecurity爲咱們提供的JSTL標籤庫,咱們能夠根據標籤庫自行判斷登陸用戶的角色,咱們修改pom.xml配置文件添加以下圖20所示依賴:
下面咱們建立main.jsp,在jsp頁面引入SpringSecurity標籤庫,並根據角色判斷輸出內容,以下圖21所示:
咱們在main.jsp判斷了是超級管理員、普通用戶的角色並根據不一樣的角色輸出不一樣的內容,下面咱們重啓項目訪問127.0.0.1:8080/main地址查看界面輸出內容,以下圖22所示:
咱們的界面並無輸出任何的內容,這是爲何呢?
SpringSecurity不支持中文比對,因此咱們這裏不能直接使用角色中文名稱做爲判斷條件,下面咱們修改roles信息表添加一個標識字段,以下圖23所示:
下面咱們對應的添加RoleEntity實體內字段,以下圖24所示:
還有最重要的一點,咱們的UserEntity內是根據RoleName來添加角色受權的,下面咱們須要改爲flag,以下圖25所示:
最後咱們修改main.jsp,hasRole改爲對應的flag字段值,以下圖26所示:
上圖的ROLE_USER、ROLE_ADMIN是咱們在roles表內的對應添加的數據,也是做爲受權的flag字段值,下面咱們重啓項目,登陸後再來訪問127.0.0.1:8080/main頁面查看界面輸出以下圖27所示:
界面爲了們輸出了兩條信息,這個是正確的,由於咱們在user_roles表內爲admin用戶添加了兩條對應的角色。下面咱們修改user_roles表結構,刪除對應普通用戶的關聯,再來訪問127.0.0.1:8080/main,界面輸出效果以下圖28所示:
咱們很奇怪,數據爲何沒有變化呢?由於SpringSecurity將咱們的用戶數據、角色數據都緩存到框架內,下面咱們來重啓下項目再次訪問後,界面輸出內容以下圖29所示:
此次界面輸出的內容纔是正確的。
以上內容就是本章的所有內容,本章主要講解了SpringBoot項目中如何使用SpringSecurity來做爲安全框架,並經過SpringSecurity提供的JSTL標籤庫來判斷界面的輸出,還有若是修改了用戶的權限不會實時生效,而須要咱們退出用戶後再次登陸方可生效。
本章的代碼以及SQL都已上傳到碼雲:
SpringBoot配套源碼地址:gitee.com/hengboy/spr…
SpringCloud配套源碼地址:gitee.com/hengboy/spr…
SpringBoot相關係列文章請訪問:目錄:SpringBoot學習目錄
QueryDSL相關係列文章請訪問:QueryDSL通用查詢框架學習目錄
SpringDataJPA相關係列文章請訪問:目錄:SpringDataJPA學習目錄
SpringBoot相關文章請訪問:目錄:SpringBoot學習目錄,感謝閱讀!
歡迎加入QQ技術交流羣,共同進步。