springboot + spring security + JWT 進行登錄驗證和權限管理

    springsecurity 分2部分,登錄驗證和權限管理,在登錄驗證成功之後會在 SecurityContextHolder 上線文中添加 Authentication 對象,包含用戶信息和角色信息,用於權限管理和系統驗證用戶信息保存。

源碼地址https://github.com/huwenhu2007/springsecurityjwt/tree/master

 

登錄驗證

  • 驗證相關類

AbstractAuthenticationProcessingFilter 信息驗證抽象類

UsernamePasswordAuthenticationFilter  登錄信息驗證攔截器,默認URL驗證 new AntPathRequestMatcher("/login", "POST"),會對 /login 請求進行攔截驗證
           AuthenticationManager 驗證管理類(接口),驗證用戶
                   authenticate 驗證傳入用戶信息與

AbstractUserDetailsAuthenticationProvider 驗證抽象類
           DaoAuthenticationProvider 實現類,從數據庫獲取信息
           UserDetailsService 調用該接口的實現類,通過登錄帳號獲取賬戶信息

  •  驗證的3種實現方式

          1. 使用默認的認證方式
                  formLogin() 基於表單登錄
                  loginPage() 登錄頁
                  defaultSuccessUrl  登錄成功後的默認處理頁
                  failuerHandler登錄失敗之後的處理器
                  successHandler登錄成功之後的處理器
                  failuerUrl登錄失敗之後系統轉向的url,默認是this.loginPage + "?error"

        配置:http.requestMatchers().antMatchers("/api/**")
        .and().authorizeRequests().antMatchers("/user","/api/user").authenticated()
        .anyRequest().authenticated()
        .and().formLogin().loginPage("/login");
        
           2. 自定義驗證攔截器
             參考:https://www.cnblogs.com/lori/p/10400564.html
   
           3. 自定義登錄驗證,將登錄驗證器中的驗證方法取出,添加到自己的驗證邏輯中,本人使用該種方式實現

    //用戶驗證
	final Authentication authentication = authenticate(username, password);
	//存儲認證信息
	SecurityContextHolder.getContext().setAuthentication(authentication);
	
	private Authentication authenticate(String username, String password) {
        try {
            //該方法會去調用userDetailsService.loadUserByUsername()去驗證用戶名和密碼,如果正確,則存儲該用戶名密碼到“security 的 context中”
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } catch (DisabledException | BadCredentialsException e) {
            throw new RuntimeException("用戶名或密碼無效");
        }
    }

權限管理

       攔截器 AbstractSecurityInterceptor 實現權限管理,由 FilterInvocationSecurityMetadataSource 的 getAttributes 方法獲取所有資源與角色的信息,然後過濾出當前資源的角色,並返回給權限管理器 AccessDecisionManager 使用,權限管理器獲取 SecurityContextHolder 上下文中保存的用戶和角色信息,判斷用戶是否有操作該資源的權限。權限足夠則直接返回,權限不夠則提示對應異常。交易異常處理器處理。

 

遇到的坑及處理方法

  • 使用自定義JWT-TOKEN過濾器JwtAuthenticationTokenFilter之後,該過濾器會忽略  web.ignoring() 和 permitAll 的配置,因爲要實現token保存在cookie的方式,導致登錄時不走帳號、密碼驗證而是走了token驗證。

   解決方法:添加 AntPathMatcher antPathMatcher = new AntPathMatcher(); 配置解析器,對不需要進行token驗證的請求進行過濾
   if(antPathMatcher.match("/auth/*", httpServletRequest.getRequestURI())){
        // 過濾不需要通過自定義過濾器的鏈接
        filterChain.doFilter(httpServletRequest, httpServletResponse);
        return ;
    }
    

  •   添加使用了註解 @Component 的自定義權限過濾器 MyFilterSecurityInterceptor 之後,該過濾器會忽略  web.ignoring() 和 permitAll 的配置。

    解決方法:去掉註解 @Component,使用new的方式創建對象添加
    httpSecurity.addFilterBefore(new MyFilterSecurityInterceptor(myInvocationSecurityMetadataSourceService, myAccessDecisionManager), FilterSecurityInterceptor.class);

 

源碼地址https://github.com/huwenhu2007/springsecurityjwt/tree/master

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章