二、基於內存的用戶、URL權限配置
1、用戶角色配置
(1)我們可以通過自定義類繼承 WebSecurityConfigurerAdapter,從而實現對 Spring Security 更多的自定義配置。比如下面樣例我們就配置了兩個用戶,以及他們對應的角色。
注意:基於內存的用戶配置在配置角色時不需要添加“ROLE_”前綴,而下文介紹的基於數據庫的認證配置角色時需要添加“ROLE_”前綴。
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
// 指定密碼的加密方式
@SuppressWarnings("deprecation")
@Bean
PasswordEncoder passwordEncoder(){
// 不對密碼進行加密
return NoOpPasswordEncoder.getInstance();
}
// 配置用戶及其對應的角色
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("123").roles("ADMIN","USER")
.and()
.withUser("hangge").password("123").roles("USER");
}
}
(2)配置完成後,重啓項目,就可以使用這兩個用戶進行登錄了。
2、配置 URL 訪問權限
(1)上面配置完畢後受保護的資源都是默認的(不同角色訪問權限也沒有什麼不同),而真正項目中我們需要根據實際情況進行角色管理。要實現這個功能只需重寫 WebSecurityConfigurerAdapter 中的另一個方法即可:
第 30 行代碼說明:
- formLogin() 方法表示開啓表單登錄,即我們之前看到的登錄頁面。
- loginProcessingUrl() 方法配置登錄接口爲“/login”,即可以直接調用“/login”接口,發起一個 POST 請求進行登錄,登錄參數中用戶名必須爲 username,密碼必須爲 password,配置 loginProcessingUrl 接口主要是方便 Ajax 或者移動端調用登錄接口。
- permitAll() 表示和登錄相關的接口都不需要認證即可訪問。
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
// 指定密碼的加密方式
@SuppressWarnings("deprecation")
@Bean
PasswordEncoder passwordEncoder(){
// 不對密碼進行加密
return NoOpPasswordEncoder.getInstance();
}
// 配置用戶及其對應的角色
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("root").password("123").roles("ADMIN","DBA")
.and()
.withUser("admin").password("123").roles("ADMIN","USER")
.and()
.withUser("hangge").password("123").roles("USER");
}
// 配置 URL 訪問權限
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() // 開啓 HttpSecurity 配置
.antMatchers("/admin/**").hasRole("ADMIN") // admin/** 模式URL必須具備ADMIN角色
.antMatchers("/user/**").access("hasAnyRole('ADMIN','USER')") // 該模式需要ADMIN或USER角色
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") // 需ADMIN和DBA角色
.anyRequest().authenticated() // 用戶訪問其它URL都必須認證後訪問(登錄後訪問)
.and().formLogin().loginProcessingUrl("/login").permitAll() // 開啓表單登錄並配置登錄接口
.and().csrf().disable(); // 關閉csrf
}
}
(2)接着在 Conctoller 中添加如下接口進行測試:
@RestController
public class HelloController {
@GetMapping("/admin/hello")
public String admin() {
return "hello admin";
}
@GetMapping("/user/hello")
public String user() {
return "hello user";
}
@GetMapping("/db/hello")
public String db() {
return "hello db";
}
@GetMapping("/hello")
public String hello() {
return "hello";
}
}
(3)接下來測試一下,我們使用 admin 用戶進行登錄,由於該用戶具有 ADMIN 和 USER 這兩個角色,所以登錄後可以訪問 /hello、/admin/hello 以及 /user/hello 這三個接口。
(4)而由於 /db/hello 接口同時需要 ADMIN 和 DBA 角色,因此 admin 用戶仍然無法訪問。