1. 程式人生 > >SpringBoot + SpringSecurity 控制授權

SpringBoot + SpringSecurity 控制授權

授權簡介

一般的人會認為,不同的角色登入進同一個系統,根據角色許可權的不同,看到的選單不同就是控制授權。其實並不是的,選單的是否顯示只是前端互動上的一個設計而已,真正需要授權的地方的介面的訪問。

普通的系統通常會有兩個端,一個是給使用者用的業務系統(比如購物商城的買家端),一個是給公司運營人員用的管理端(可以統計銷售量,使用者量等資訊)。
業務端的許可權通常比較簡單,可以區分為是否登入,或者簡單的角色區分(比如普通使用者,VIP使用者)。管理端就相對複雜了,公司越大角色就越多,許可權就分得越細緻。

是否登入授權

簡單角色的區分

同樣是在自己繼承了AbstractChannelSecurityConfig

類的configure方法中配置

@Configuration
public class BrowerSecurityConfig extends AbstractChannelSecurityConfig {
    http.authorizeRequests()        // 定義哪些URL需要被保護、哪些不需要被保護
        .antMatchers("/user/regist", "/session/invalid")
        .permitAll()                // 設定所有人都可以訪問的介面
        .antMatchers("/user").hasRole("ADMIN"
) // user介面只有ADMIN角色的可以訪問 .anyRequest() // 其他任何請求,登入後可以訪問 .authenticated() .and() }

這裡主要通過antMatchershasRole搭配使用,進行角色許可權的控制,那麼角色許可權是在哪裡賦值的呢? 是在登入管理那兒

@Component
public class MyUserDetailsService implements UserDetailsService {
@Override
    public UserDetails loadUserByUsername
(String username) throws UsernameNotFoundException { // 演示用,隨便給一個password String password = "123456"; // 引數分別是:使用者名稱,密碼,使用者許可權 User user = new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN)); return user; } }

AuthorityUtils.commaSeparatedStringToAuthorityList接受一個字串陣列,裡面就是使用者的角色,比如在上面hasRole裡配置的是”ADMIN”,則這裡需要傳入”ROLE_ADMIN”,ADMIN是要區分大小寫的。

在使用restfulAPI的時候,介面地址是一樣,但是請求方法不一樣,這個時候antMatchers裡還可以配置請求方法

// 此時POST方法會需要角色許可權
antMatchers(HttpMethod.POST, "/user").hasRole("ADMIN")

複雜角色許可權 以及 許可權表示式

之前的許可權配置都是直接通過程式碼寫在配置中的
當面對有複雜角色的時候,一般是把角色與許可權放在資料庫中的。這個時候一般會涉及到五個資料庫表,分別是:使用者表、角色表、許可權表,使用者與角色中間表,角色與許可權中間表。

這裡我們模擬一個從資料庫中根據當前帳號獲取許可權的示例

@Component("rbacPermission")
public class RbacPermission {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        Object principal = authentication.getPrincipal();
        boolean hasPermission = false;
        if(principal instanceof UserDetails) {
            String username = ((UserDetails) principal).getUsername();
            // 讀取使用者所擁有的許可權url,這裡應該從資料庫獲取
            Set<String> urls = new HashSet<>();

            for (String url : urls) {
                // 判斷當前url是否有許可權
                if(antPathMatcher.match(url, request.getRequestURI())) {
                    hasPermission = true;
                    break;
                }
            }
        }
        return hasPermission;
    }
}

接下來就是配置一下了

http.authorizeRequests()
     .anyRequest()
     .access("@rbacPermission.hasPermission(request, authentication)");

access中的就是許可權表示式

需要注意的是,anyRequest()需要放在最後

程式碼下載