
一、formLogin的應用場景
在本專欄之前的文章中,已經給大家介紹過Spring Security的HttpBasic模式,該模式比較簡單,只是進行了通過攜帶Http的Header進行簡單的登錄驗證,而且沒有定制的登錄頁面,所以使用場景比較窄。
對於一個完整的應用系統,與登錄驗證相關的頁面都是高度定制化的,非常美觀而且提供多種登錄方式。這就需要Spring Security支持我們自己定制登錄頁面,也就是本文給大家介紹的formLogin模式登錄認證模式。
准備工作
- 新建一個Spring Boot 的web應用,引入Spring Security Starter。
- 准備一個login.html登錄頁面,頁面內容非常簡單,一個from表單、用戶名和密碼輸入框,一個提交按鈕
- 准備一個首頁index.html,在登錄成功之后需要進入index.html首頁
- 首頁可以看到syslog(日志管理)、sysuer(用戶管理)、biz1(業務一)、biz2(業務二)四個頁面超文本鏈接選項。通過controller控制層跳轉頁面,並在對應頁面寫一些標志性文字即可,不需寫具體業務。
需求
- 我們希望biz1(業務一)、biz2(業務二)普通的操作用戶user就可以訪問
- 我們希望管理員可以訪問包括syslog(日志管理)和sysuser(用戶管理)在內的所有資源
以上就是本文介紹formLogin模式需要進行的准備工作及需求,下面我們就來實現其中的核心的登錄驗證邏輯,准備工作非常簡單請自行實現。(新建spring boot應用,登錄頁面、首頁、四個業務頁面都寫成非常簡單的html即可,不用寫實際業務和樣式。)
二、說明
formLogin模式的三要素:
- 登錄驗證邏輯
- 資源訪問控制規則,如:資源權限、角色權限
- 用戶信息
一般來說,使用權限認證框架的的業務系統登錄驗證邏輯是固定的,而資源訪問控制規則和用戶信息是從數據庫或其他存儲介質靈活加載的。但本文所有的用戶、資源、權限信息都是代碼配置寫死的,旨在為大家介紹formLogin認證模式,如何從數據庫加載權限認證相關信息我還會結合RBAC權限模型再寫文章的。
三、實現formLogin模式基礎配置
首先,我們要繼承WebSecurityConfigurerAdapter ,重寫configure(HttpSecurity http) 方法,該方法用來配置登錄驗證邏輯。請注意看下文代碼中的注釋信息。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //禁用跨站csrf攻擊防御,后面的章節會專門講解
.formLogin()
.loginPage("/login.html")//用戶未登錄時,訪問任何資源都轉跳到該路徑,即登錄頁面
.loginProcessingUrl("/login")//登錄表單form中action的地址,也就是處理認證請求的路徑
.usernameParameter("uname")///登錄表單form中用戶名輸入框input的name名,不修改的話默認是username
.passwordParameter("pword")//form中密碼輸入框input的name名,不修改的話默認是password
.defaultSuccessUrl("/index")//登錄認證成功后默認轉跳的路徑
.and()
.authorizeRequests()
.antMatchers("/login.html","/login").permitAll()//不需要通過登錄驗證就可以被訪問的資源路徑
.antMatchers("/biz1").hasAnyAuthority("biz1") //前面是資源的訪問路徑、后面是資源的名稱或者叫資源ID
.antMatchers("/biz2").hasAnyAuthority("biz2")
.antMatchers("/syslog").hasAnyAuthority("syslog")
.antMatchers("/sysuser").hasAnyAuthority("sysuser")
.anyRequest().authenticated();
}
}
上面的代碼分為兩部分:
- 第一部分是formLogin配置段,用於配置登錄驗證邏輯相關的信息。如:登錄頁面、登錄成功頁面、登錄請求處理路徑等。
- 第二部分是authorizeRequests配置端,用於配置資源的訪問權限。如:開發登錄頁面的permitAll開放訪問,“/biz1”(業務一頁面資源)需要有資源ID為"biz1"的用戶才可以訪問。
這時候,我們通過瀏覽器訪問,隨便測試一個沒有訪問權限的資源,都會跳轉到login.html頁面。

四、實現資源訪問限制的需求
在上文中,我們配置了登錄驗證及資源訪問的權限規則,我們還沒有具體的用戶,下面我們就來配置具體的用戶。重寫WebSecurityConfigurerAdapter的 configure(AuthenticationManagerBuilder auth)方法
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password(passwordEncoder().encode("123456")).authorities("biz1","biz2")
.and()
.passwordEncoder(passwordEncoder());//配置BCrypt加密
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
inMemoryAuthentication指的是在內存里面存儲用戶的身份認證和授權信息。withUser("user")用戶名是userpassword(passwordEncoder().encode("123456"))密碼是加密之后的123456authorities("biz1","biz2")指的是user用戶擁有資源ID為biz1(業務一)和biz2(業務二)資源的權限
這樣,我們就實現了文首提出的普通用戶只能訪問biz1(業務一)和biz2(業務二)資源的需求。那么管理員用戶可以訪問所有的資源的配置方式,你會不會呢?同樣的配方、同樣的方式、自己可以嘗試一下哦!
五、靜態資源訪問
在我們的實際開發中,登錄頁面login.html和控制層Controller登錄驗證'/login'都必須無條件的開放。除此之外,一些靜態資源如css、js文件通常也都不需要驗證權限,我們需要將它們的訪問權限也開放出來。下面就是實現的方法:重寫WebSecurityConfigurerAdapter類的configure(WebSecurity web) 方法
@Override
public void configure(WebSecurity web) {
//將項目中靜態資源路徑開放出來
web.ignoring().antMatchers("/config/**", "/css/**", "/fonts/**", "/img/**", "/js/**");
}
期待您的關注
- 博主最近新寫了一本書:《手摸手教您學習SpringBoot系列-16章97節》
- 本文轉載注明出處(必須帶連接,不能只轉文字):字母哥博客。
