Spring Security實戰三:說說我的認識

weixin_34236497發表於2018-08-08

Spring Security的用法看了不少,就大概來總結總結,找出一套適合直接應用到專案的。

一、為什麼要用Spring Security

待補充

二、Spring Security整合中的缺點

  Spring Security的主要功能是登入驗證、訪問控制。然而,由於Remember Me和訪問控制自身的缺陷,導致並不適用在實際的專案中。Remember Me的缺陷參考上篇文章:關於記住HTTP請求的狀態;訪問控制的不足,主要是因為要把許可權控制硬編碼在程式碼中。為了解決這兩個問題,考慮引入JWT+redis(JWT)和RBAC。

1.引入JWT+redis

  1)講講JWT的優缺點。2)引入redis解決其重新整理的問題有兩種方式。①時時更新 ②儲存一個上次訪問時間,在JWT過期時,比較兩次時間的差值來確定,是否需要動態更新JWT。
待補充

2.引入RBAC

  RBAC的引入分三步:先設計資料庫,再編寫增刪改查操作,最後將RBAC應用到Spring Security中。前兩步就省略了,直接看第三步吧,怎麼在Spring Security中使用RBAC。
首先,判斷當前使用者所擁有的URL是否和當前訪問的URL是否匹配

/**
 * 返回許可權驗證的介面
 */
public interface RbacService {
      boolean hasPermission(HttpServletRequest request,Authentication authentication);
}

@Component("rbacService")
public class RbacServiceImpl implements RbacService {
      private AntPathMatcher antPathMatcher = new AntPathMatcher();
      @Override
      public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
            Object principal = authentication.getPrincipal();
            boolean hasPermission = false;
            if (principal instanceof UserDetails) { //首先判斷先當前使用者是否是我們UserDetails物件。
                  String userName = ((UserDetails) principal).getUsername();
                  Set<String> urls = new HashSet<>(); // 資料庫讀取 //讀取使用者所擁有許可權的所有URL
                  
                  urls.add("/whoim");
                  // 注意這裡不能用equal來判斷,因為有些URL是有引數的,所以要用AntPathMatcher來比較
                  for (String url : urls) {
                        if (antPathMatcher.match(url, request.getRequestURI())) {
                              hasPermission = true;
                              break;
                        }
                  }
            }
            return hasPermission;
      }
}

然後將此訪問控制配置在Spring Security中

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()  //表單登入
                //.loginPage("/evolutionary-loginIn.html")
                .loginPage("/logintype") //如果需要身份認證則跳轉到這裡
                .loginProcessingUrl("/login")
                .successHandler(evolutionaryAuthenticationHandler)
                .failureHandler(evolutionaryAuthenticationFailureHandler)
                .and()
                .authorizeRequests()
                .antMatchers("/logintype",securityProperties.getBrower().getLoginPage())//不校驗我們配置的登入頁面
                .permitAll()
                .anyRequest()
                .access("@rbacService.hasPermission(request,authentication)")    //必須經過認證以後才能訪問
                .and().csrf().disable().addFilter(new JWTLoginFilter(authenticationManager()))
                .addFilter(new JWTAuthenticationFilter(authenticationManager()));
    }

相關文章