發現不多關於spring security的文章,基本都是入門級的,配個UserServiceDetails或者配個路由控制就完事了,並且不少仍是xml配置,國內通病...so,本文裏的配置都是java配置,不涉及xml配置,事實上我也不會xml配置java
spring security自己若是隻是說配置,仍是很簡單易懂的(我也不知道網上說spring security難,難在哪裏),簡單不須要特別的功能,一個WebSecurityConfigurerAdapter的實現,而後實現UserServiceDetails就是簡單的數據庫驗證了,這個我就不說了。web
spring security大致上是由一堆Filter(因此才能在spring mvc前攔截請求)實現的,Filter有幾個,登出Filter(LogoutFilter),用戶名密碼驗證Filter(UsernamePasswordAuthenticationFilter)之類的,Filter再交由其餘組件完成細分的功能,例如最經常使用的UsernamePasswordAuthenticationFilter會持有一個AuthenticationManager引用,AuthenticationManager顧名思義,驗證管理器,負責驗證的,但AuthenticationManager自己並不作具體的驗證工做,AuthenticationManager持有一個AuthenticationProvider集合,AuthenticationProvider纔是作驗證工做的組件,AuthenticationManager和AuthenticationProvider的工做機制能夠大概看一下這兩個的java doc,而後成功失敗都有相對應該Handler 。大致的spring security的驗證工做流程就是這樣了。spring
package com.scau.equipment.config.common.security.provider; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; /** * Created by Administrator on 2017-05-10. */ @Component public class InMemoryAuthenticationProvider implements AuthenticationProvider { private final String adminName = "root"; private final String adminPassword = "root"; //根用戶擁有所有的權限 private final List<GrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority("CAN_SEARCH"), new SimpleGrantedAuthority("CAN_SEARCH"), new SimpleGrantedAuthority("CAN_EXPORT"), new SimpleGrantedAuthority("CAN_IMPORT"), new SimpleGrantedAuthority("CAN_BORROW"), new SimpleGrantedAuthority("CAN_RETURN"), new SimpleGrantedAuthority("CAN_REPAIR"), new SimpleGrantedAuthority("CAN_DISCARD"), new SimpleGrantedAuthority("CAN_EMPOWERMENT"), new SimpleGrantedAuthority("CAN_BREED")); @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { if(isMatch(authentication)){ User user = new User(authentication.getName(),authentication.getCredentials().toString(),authorities); return new UsernamePasswordAuthenticationToken(user,authentication.getCredentials(),authorities); } return null; } @Override public boolean supports(Class<?> authentication) { return true; } private boolean isMatch(Authentication authentication){ if(authentication.getName().equals(adminName)&&authentication.getCredentials().equals(adminPassword)) return true; else return false; } }
support方法檢查authentication的類型是否是這個AuthenticationProvider支持的,這裏我簡單地返回true,就是全部都支持,這裏所說的authentication爲何會有多個類型,是由於多個AuthenticationProvider能夠返回不一樣的Authentication。數據庫
public Authentication authenticate(Authentication authentication) throws AuthenticationException 方法就是驗證過程。api
若是AuthenticationProvider返回了null,AuthenticationManager會交給下一個支持authentication類型的AuthenticationProvider處理。mvc
@Bean DaoAuthenticationProvider daoAuthenticationProvider(){ DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder()); daoAuthenticationProvider.setUserDetailsService(userServiceDetails); return daoAuthenticationProvider; }
1 package com.scau.equipment.config.common.security; 2 3 import com.scau.equipment.config.common.security.handler.AjaxLoginFailureHandler; 4 import com.scau.equipment.config.common.security.handler.AjaxLoginSuccessHandler; 5 import com.scau.equipment.config.common.security.provider.InMemoryAuthenticationProvider; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.context.annotation.Bean; 8 import org.springframework.context.annotation.Configuration; 9 import org.springframework.security.authentication.AuthenticationManager; 10 import org.springframework.security.authentication.ProviderManager; 11 import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 12 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 13 import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer; 14 import org.springframework.security.config.annotation.authentication.configurers.provisioning.UserDetailsManagerConfigurer; 15 import org.springframework.security.config.annotation.web.builders.HttpSecurity; 16 import org.springframework.security.config.annotation.web.builders.WebSecurity; 17 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 18 import org.springframework.security.core.GrantedAuthority; 19 import org.springframework.security.core.authority.SimpleGrantedAuthority; 20 import org.springframework.security.core.userdetails.UserDetailsService; 21 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 22 23 import java.util.Arrays; 24 import java.util.List; 25 26 /** 27 * Created by Administrator on 2017/2/17. 28 */ 29 @Configuration 30 public class SecurityConfig extends WebSecurityConfigurerAdapter { 31 32 @Autowired 33 UserDetailsService userServiceDetails; 34 35 @Autowired 36 InMemoryAuthenticationProvider inMemoryAuthenticationProvider; 37 38 @Bean 39 DaoAuthenticationProvider daoAuthenticationProvider(){ 40 DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); 41 daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder()); 42 daoAuthenticationProvider.setUserDetailsService(userServiceDetails); 43 return daoAuthenticationProvider; 44 } 45 46 @Override 47 protected void configure(HttpSecurity http) throws Exception { 48 http 49 .csrf().disable() 50 .rememberMe().alwaysRemember(true).tokenValiditySeconds(86400).and() 51 .authorizeRequests() 52 .antMatchers("/","/*swagger*/**", "/v2/api-docs").permitAll() 53 .anyRequest().authenticated().and() 54 .formLogin() 55 .loginPage("/") 56 .loginProcessingUrl("/login") 57 .successHandler(new AjaxLoginSuccessHandler()) 58 .failureHandler(new AjaxLoginFailureHandler()).and() 59 .logout().logoutUrl("/logout").logoutSuccessUrl("/"); 60 } 61 62 @Override 63 public void configure(WebSecurity web) throws Exception { 64 web.ignoring().antMatchers("/public/**", "/webjars/**", "/v2/**", "/swagger**"); 65 } 66 67 @Override 68 protected AuthenticationManager authenticationManager() throws Exception { 69 ProviderManager authenticationManager = new ProviderManager(Arrays.asList(inMemoryAuthenticationProvider,daoAuthenticationProvider())); 70 //不擦除認證密碼,擦除會致使TokenBasedRememberMeServices由於找不到Credentials再調用UserDetailsService而拋出UsernameNotFoundException 71 authenticationManager.setEraseCredentialsAfterAuthentication(false); 72 return authenticationManager; 73 } 74 75 /** 76 * 這裏須要提供UserDetailsService的緣由是RememberMeServices須要用到 77 * @return 78 */ 79 @Override 80 protected UserDetailsService userDetailsService() { 81 return userServiceDetails; 82 } 83 }
基本上都是重用了原有的類,不少都是默認使用的,只不過爲了修改下行爲而從新配置。其實若是偷懶,直接用一個UserDetailsService,在裏面作各類認證也是能夠的~不過這樣就沒意思了ide