security的簡單原理:
使用衆多的攔截器對url攔截,以此來管理權限。但是這麼多攔截器,不可能對其一一來講,主要講裏面核心流程的兩個。
首先,權限管理離不開登陸驗證的,所以登陸驗證攔截器AuthenticationProcessingFilter要講;還有就是對訪問的資源管理吧,所以資源管理攔截器AbstractSecurityInterceptor要講;但攔截器裏面的實現需要一些組件來實現,所以就有了AuthenticationManager、accessDecisionManager等組件來支撐。
現在先大概過一遍整個流程,用戶登陸,會被AuthenticationProcessingFilter攔截,調用AuthenticationManager的實現,而且AuthenticationManager會調用ProviderManager來獲取用戶驗證信息(不同的Provider調用的服務不同,因爲這些信息可以是在數據庫上,可以是在LDAP服務器上,可以是xml配置文件上等),如果驗證通過後會將用戶的權限信息封裝一個User放到spring的全局緩存SecurityContextHolder中,以備後面訪問資源時使用。
訪問資源(即授權管理),訪問url時,會通過AbstractSecurityInterceptor攔截器攔截,其中會調用FilterInvocationSecurityMetadataSource的方法來獲取被攔截url所需的全部權限,在調用授權管理器AccessDecisionManager,這個授權管理器會通過spring的全局緩存SecurityContextHolder獲取用戶的權限信息,還會獲取被攔截的url和被攔截url所需的全部權限,然後根據所配的策略(有:一票決定,一票否定,少數服從多數等),如果權限足夠,則返回,權限不夠則報錯並調用權限不足頁面。
雖然講得好像好複雜,讀者們可能有點暈,不過不打緊,真正通過代碼的講解在後面,讀者可以看完後面的代碼實現,再返回看這個簡單的原理,可能會有不錯的收穫。
在spring boot中使用security
首先導入spring security的包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
在spring security中有一個非常重要的配置類需要編寫
就是繼承這個抽象類WebSecurityConfigurerAdapter,如下代碼所示
這個bean的目的是將我們的用戶存到內存中,這個用於調試還是可以的,但是我們開發中是不存在這樣的
@Bean
@Override
protected UserDetailsService userDetailsService(){
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user_1").password("123456").authorities("USER").build());
manager.createUser(User.withUsername("user_2").password("123456").authorities("USER").build());
return manager;
}
上面這步完成後還需要我們將userdetail的類給添加到攔截器中,因爲我們登錄是需要進行驗證用戶的,所以可以直接
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
這裏面還可以設置其他參數,比如加密的方式以及其他等等。
在這個類中海可以設置一寫忽略的攔截類,即不需要進行驗證的
/**
* 忽略設置的接口
*/
@Override
public void configure(WebSecurity web) throws Exception {
String ignoring = env.getProperty("msi.auth.ignoring","/health|/info");
web.ignoring().antMatchers(ignoring.split("\\|"));
}
不管是使用哪種方式,將用戶存到內存或者存到數據庫操作,都需要將操作放到
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}