spring-boot啟用security組件 · 上

前言
從今天開始,我打算系統(tǒng)地回顧下spring-boot的相關(guān)知識,但是在系統(tǒng)學(xué)習(xí)之前,我想先把之前沒有了解過的知識過一遍,之后再系統(tǒng)地總結(jié)。今天我們就先來看下spring-boot的官方組件secutity,下面我們就直接開始吧!
Security組件
這個組件是spring-boot的基礎(chǔ)組件之一,主要用于spring-boot項目的權(quán)限控制,我們今天主要是看下它的基礎(chǔ)配置和一些簡單應(yīng)用。
開始之前,我們要先創(chuàng)建一個spring-boot項目。
創(chuàng)建項目
項目的依賴很簡單,最核心的依賴就兩個,一個就是spring-boot-starter,這個依賴是spring-boot最基礎(chǔ)的依賴,沒有之一,但凡你創(chuàng)建spring-boot項目都會有這個依賴;
另外一個核心依賴就是我們今天的主角——spring-boot-starter-security;
除了兩個核心依賴,我還引入了guava的依賴,這是一個谷歌出品的工具類包,其中有很多特別方便的工具類,比如容器操作。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
<!-- or, for Android: -->
<!--<version>30.1.1-android</version>-->
</dependency>
加入以上配置之后,我們不需要做任何配置,security其實已經(jīng)被我們集成到spring-boot中了,不信你啟動下看看:

如果你的控制臺也有如上信息,說明你的spring-boot項目已經(jīng)集成了security,最上面打印的就是我們的登錄密碼,用戶名默認(rèn)情況下是user,下面我們簡單測試下。
測試
首先,我們要寫一個controller,沒有controller的話,確實不好測試。controller中,我就寫了一個簡單的testSecurity方法,方法內(nèi)部打印helle信息。
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("security")
public Object testSecurity(String name) {
return "hello, " + name;
}
}
controller創(chuàng)建完成后,我們再次啟動項目,然后訪問http://localhost:8989/test/security?name=syske

正常情況下,會跳轉(zhuǎn)到登錄頁面,這就說明security組件已經(jīng)起作用了。

這里登錄的用戶名是user,密碼就是控制臺打印出來的密碼,輸入用戶名和密碼,然后登錄,這時候接口就正常返回了:

登錄成功后,你后面再訪問其他接口也是不需要再次登陸的。而且我試過,就算你關(guān)閉瀏覽器,再次打開,也是不需要登陸的,但是你重啟spring-boot服務(wù)之后,就需要重新登錄了,目前還不清楚具體的鑒權(quán)原理,從瀏覽器請求情況來看,不是token,后面研究下。
security雖然起作用了,但是我們在實際應(yīng)用的時候,不可能都用user和默認(rèn)密碼登錄吧,畢竟不方便,也不合理,所以下面我們就來看下如何來配置security,讓它滿足我們更復(fù)雜的應(yīng)用場景。
配置security
首先,我們要創(chuàng)建一個配置類,這個配置類要繼承WebSecurityConfigurerAdapter,并重寫其中的configure方法,這個類有多個configure方法,這里我們重寫的是參數(shù)為AuthenticationManagerBuilder,其他配置類,我們后面繼續(xù)講。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
@Autowired
private ReaderRepository readerRepository;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(username -> {
System.out.println(username);
return readerRepository.loadUserByUsername(username);
}).passwordEncoder(new BCryptPasswordEncoder());
}
}
這個方法其實就是用戶登錄時的鑒權(quán)方法,我們通過重寫這個方法,可以實現(xiàn)我們自己的鑒權(quán)操作。我這里現(xiàn)在都是寫死的,只要你登錄的用戶是admin,就可以鑒權(quán)通過,密碼我也是寫死的。
userDetailsService方法的作用是配置用戶信息查詢服務(wù),我們需要繼承UserDetailsService接口,并實現(xiàn)其中的loadUserByUsername方法,這個方法會返回 UserDetails,也就是用戶基本信息,主要是密碼和用戶名,還有過期時間這些:

下面是我寫的一個構(gòu)建UserDetails的服務(wù),后期的話,可以根據(jù)自己的需要整合數(shù)據(jù)庫。
@Service
public class ReaderRepository implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if ("admin".equals(username)) {
return new UserInfo("admin", new BCryptPasswordEncoder()
.encode("admin"));
} else {
return null;
}
}
public static class UserInfo implements UserDetails {
private String username;
private String password;
public UserInfo(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("READER"));
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
}
然后,重啟我們的spring-boot項目,這時候我們就不能用默認(rèn)的用戶名和密碼登錄了,控制臺也不會有密碼打印了,而是用我們設(shè)置的用戶名和密碼登錄。
這里需要注意的是,passwordEncoder(new BCryptPasswordEncoder())的作用是指定密碼的加密器,這里的加密器必須和你保存密碼時用的加密器一致,否則密碼校驗無法通過。
如果你不指定密碼加密器,鑒權(quán)的時候也是會報錯的:

另外,還有一點比較重要,就是我們在登錄的時候,其實就是調(diào)用userDetailsService的loadUserByUsername獲取用戶信息,然后進(jìn)行鑒權(quán)操作,所以如果要修改security組件的相關(guān)配置,就必須實現(xiàn)loadUserByUsername方法,這樣才能確保你的用戶數(shù)據(jù)是可控的。
總結(jié)
今天我們分享了spring-boot啟用security組件的相關(guān)知識點,整個過程還是比較簡單,但是由于時間的關(guān)系,好些點我們沒有展開來講,也講的不夠細(xì),不過也沒有關(guān)系,因為最近一段時間我們都打算分享spring-boot相關(guān)知識,所以明天我們會繼續(xù)分享.
好了,今天的內(nèi)容就到這里吧,我們明天繼續(xù)。
- END -