SpringBoot + SpringSecurity 控制授權
阿新 • • 發佈:2019-01-01
授權簡介
一般的人會認為,不同的角色登入進同一個系統,根據角色許可權的不同,看到的選單不同就是控制授權。其實並不是的,選單的是否顯示只是前端互動上的一個設計而已,真正需要授權的地方的介面的訪問。
普通的系統通常會有兩個端,一個是給使用者用的業務系統(比如購物商城的買家端),一個是給公司運營人員用的管理端(可以統計銷售量,使用者量等資訊)。
業務端的許可權通常比較簡單,可以區分為是否登入,或者簡單的角色區分(比如普通使用者,VIP使用者)。管理端就相對複雜了,公司越大角色就越多,許可權就分得越細緻。
是否登入授權
簡單角色的區分
同樣是在自己繼承了AbstractChannelSecurityConfig
@Configuration
public class BrowerSecurityConfig extends AbstractChannelSecurityConfig {
http.authorizeRequests() // 定義哪些URL需要被保護、哪些不需要被保護
.antMatchers("/user/regist", "/session/invalid")
.permitAll() // 設定所有人都可以訪問的介面
.antMatchers("/user").hasRole("ADMIN" ) // user介面只有ADMIN角色的可以訪問
.anyRequest() // 其他任何請求,登入後可以訪問
.authenticated()
.and()
}
這裡主要通過antMatchers
和hasRole
搭配使用,進行角色許可權的控制,那麼角色許可權是在哪裡賦值的呢? 是在登入管理那兒
@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()需要放在最後