前三章主要講的是Security對於認證的處理,那麼本節,會爲你們介紹基於Security默認表達式的權限控制(較爲簡單,沒法知足複雜權限控制及多變的權限規則,後面會介紹基於自定義表達式的權限訪問控制,可知足99%的業務場景的需求)。java
直接進入主題,基於默認的表達式權限控制,須要在SecurityConfig中配置,代碼以下:app
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired private SecurityProperties securityProperties; @Autowired private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler; @Autowired private MyAuthenticationFailureHandler myAuthenticationFailureHandler; @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http .formLogin() .loginPage(securityProperties.getToLoginProperties().getLoginProperties().getLoginPage())//用戶未認證時,轉跳到認證的頁面 .loginProcessingUrl(securityProperties.getToLoginProperties().getLoginProperties().getLoginProcessingUrl())//form中action的地址,也就是處理認證請求的URL .usernameParameter(securityProperties.getToLoginProperties().getLoginProperties().getUsernameParameter())//form中用戶名密碼的name名 .passwordParameter(securityProperties.getToLoginProperties().getLoginProperties().getPasswordParameter()) .defaultSuccessUrl(securityProperties.getToLoginProperties().getLoginProperties().getDefaultSuccessUrl())//認證成功後默認轉跳的URL .successHandler(myAuthenticationSuccessHandler) .failureHandler(myAuthenticationFailureHandler) .and() .authorizeRequests() .antMatchers(securityProperties.getToLoginProperties().getLoginProperties().getLoginPage(), securityProperties.getToLoginProperties().getLoginProperties().getLoginProcessingUrl()).permitAll() .antMatchers(HttpMethod.GET,"/vip").hasRole("admin")//默認權限表達式 .anyRequest().authenticated() .and() .csrf().disable() ; } }
上面代碼的含義是,「/vip」這個URL必須是GET請求,且擁有admin權限的用戶才能夠訪問。接下來咱們配置一下UserDetailServer,模擬給用戶一個admin權限。框架
@Component public class MyUserDetailsServer implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // TODO Auto-generated method stub if("admin".equals(username)){ throw new RuntimeException("admin禁止登陸"); } return new User(username, "$2a$10$ofPkBDUezOJp6Sik63Q/0.QlU8a1itEyzldjSXqfn2nDPqXjN0Ljm", AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); } }
AuthorityUtils是Security提供的一個工具類,我使用的這個方法的功能是將一個以「,」分割的字符串轉換成UserDetail中第三個參數所須要的Collection<? extends GrantedAuthority>。ide
所有配置好後咱們重啓項目,登陸。能夠看到,我是擁有admin這個權限的,按道理說我有權限訪問「/vip」,咱們訪問一下試試。工具
奇怪?我明明擁有「admin」權限,爲何訪問「/vip」確是403,請求被拒絕呢?spa
第一節中,咱們明明能夠在Authorites看到當前用戶擁有了admin權限,可是卻訪問被拒絕!這又是爲何呢?下面,我帶着你們走一邊Security的源碼,看一看究竟是哪裏出現了問題。code
咱們依舊在UserdetailsServer中打上斷點。orm
重啓項目,登錄後,訪問「/vip」查看斷點堆棧信息。咱們只看最後一個過濾器,這裏咱們說過,他會讀取咱們的SecurityConfig的配置信息,作匹配。咱們能夠看到雖然咱們配置的「/vip」須要的權限是admin,可是框架卻自動爲咱們加上了「ROLE_」的前綴,因此,這就是咱們爲何匹配不到,無權限訪問的緣由。csrf
咱們稍做修改,將UserDetailsServer中的權限加上這個前綴。ip
咱們重啓項目,再次訪問,能夠看到已經有權限了,404是因爲我沒有寫這個頁面。
在前面的介紹中,不管是403仍是404,咱們使用的都是提供的默認頁面實現,而在咱們的實際業務中須要咱們使用本身的異常頁面,那麼怎麼配置呢?方法有不少種,好比404頁面,咱們能夠寫一個不徹底匹配的@RequestMapping 這樣因爲不徹底匹配的優先級是小於徹底匹配的優先級的,因此當匹配不到映射的時候就會匹配咱們的404了。
可是我既然單獨拿出來寫一章,其實徹底爲了湊字數(一不當心說了實話),那確定就是有更好的方法的,其實在Spring Boot中,只須要在默認靜態資源目錄下建立一個與狀態碼同名的頁面,就會在出現異常的時候進入到你的頁面中。至於Spring boot的默認資源目錄是什麼,怎麼改,請看個人Spring boot系列博客。
咱們訪問試一下: