在之前的文章樣例中,認證和授權都是基於 URL 的。開發者也可以通過註解來靈活地配置方法安全,下面通過樣例進行演示。
十、通過註解配置方法安全
1、樣例代碼
(1)首先我們要通過 @EnableGlobalMethodSecurity 註解開啓基於註解的安全配置:
@EnableGlobalMethodSecurity 註解參數說明:
- prePostEnabled = true 會解鎖 @PreAuthorize 和 @PostAuthorize 兩個註解。顧名思義,@PreAuthorize 註解會在方法執行前進行驗證,而 @PostAuthorize 註解會在方法執行後進行驗證。
- securedEnabled = true 會解鎖 @Secured 註解。
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
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("DBA")
.and()
.withUser("admin").password("123").roles("ADMIN")
.and()
.withUser("hangge").password("123").roles("USER");
}
// 配置 URL 訪問權限
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() // 開啓 HttpSecurity 配置
.anyRequest().authenticated() // 用戶訪問其它URL都必須認證後訪問(登錄後訪問)
.and().formLogin().loginProcessingUrl("/login").permitAll() // 開啓表單登錄並配置登錄接口
.and().csrf().disable(); // 關閉csrf
}
}
(2)開啓註解安全配置後,接着創建一個 MethodService 進行測試:
@Service
public class MethodService {
// 訪問該方法需要 ADMIN 角色。注意:這裏需要在角色前加一個前綴"ROLE_"
@Secured("ROLE_ADMIN")
public String admin() {
return "hello admin";
}
// 訪問該方法既要 ADMIN 角色,又要 DBA 角色
@PreAuthorize("hasRole('ADMIN') and hasRole('DBA')")
public String dba() {
return "hello dba";
}
// 訪問該方法只需要 ADMIN、DBA、USER 中任意一個角色即可
@PreAuthorize("hasAnyRole('ADMIN','DBA','USER')")
public String user() {
return "hello user";
}
}
(3)最後在 Controller 中注入這個 Service 並調用 Service 中的方法進行測試:
@RestController
public class HelloController {
@Autowired
MethodService methodService;
@GetMapping("/admin")
public String admin() {
return methodService.admin();
}
@GetMapping("/dba")
public String dba() {
return methodService.dba();
}
@GetMapping("/user")
public String user() {
return methodService.user();
}
}
2、運行測試
(1)使用 admin 用戶登錄,無論訪問 /admin 接口、還是 /user 接口都是沒問題的:
(2)而對於 /dba 接口雖然 admin 也有權限,但該接口內部調用的 methodService.dba() 方法同時需要 ADMIN 和 DBA 權限,因此訪問會被拒絕。