1.先根據用戶查詢出菜單
2根據用戶發送過來的URL資源請求判斷那些角色可以訪問
3.根據當前用戶登陸的角色和數據庫裏角色做個比對
例如
1.查詢資源表id 7
的路徑,對應的中間表7
- 6
,查詢到的是角色表的id 7
系統管理員
2.根據用戶表id 3
管理員名字,對應的中間表是rid 6
,查詢出角色表id 6
系統管理員
此優點:是沒有在代碼中寫死,如果想改,可以到數據庫修改權限
資源表
資源表和角色表
角色表
用戶表
用戶角色中間表
實體類中包含菜單和角色集合
/**
* 菜單實體類
*/
public class Menu {
private Integer id; //id
private String url;//路徑
private String path;
private String component; //組件的名
private String name; //菜單名
private String iconcls; //圖片
private Boolean keepalive;
private Boolean requireauth;
private Integer parentid;
private Boolean enabled; //是否啓動
private List<Menu> children; //菜單
private List<Role> roles; //角色
獲取登陸用戶ID,返回用戶菜單
/**
*
* @return 獲取登陸用戶ID,返回用戶菜單
*/
public List<Menu> getMenusByHrId() {
return menuMapper.getMenusByHrId(((Hr) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId());
}
查詢出用戶
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
Hr hr = hrMapper.loadUserByUsername(s);
if (hr == null){
throw new UsernameNotFoundException("用戶不存在");
}
hr.setRoles(roleMapper.getRolesByHrId(hr.getId()));//根據用戶獲取角色id
return hr;
}
2.使用攔截器過濾當前請求中的角色
@Component
public class MyFilter implements FilterInvocationSecurityMetadataSource {
@Autowired
MenuService menuService; //查詢出菜單
AntPathMatcher antPathMatcher = new AntPathMatcher(); //路徑匹配
/**
*
* @param o 發來的請求中提取當前請求地址
* @return 返回當前請求需要的角色
* @throws IllegalArgumentException
*/
@Override
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
String requestUrl = ((FilterInvocation) o).getRequestUrl(); //調用過濾器攔截當前請求地址
List<Menu> list = menuService.getAllMenus(); //數據庫查詢出菜單
for (Menu menu :list){
if (antPathMatcher.match(menu.getUrl(),requestUrl)){ //匹配數據庫URL地址
List<Role> roles = menu.getRoles(); //get角色訪問
String[] strArr = new String[roles.size()];
for (int i = 0;i<roles.size();i++){
strArr[i] = roles.get(i).getName();
}
return SecurityConfig.createList(strArr);//返回角色
}
}
return SecurityConfig.createList("ROLB_LOGIN");//沒有角色就做個標記
}
3.當前用戶是否具備有這樣的角色
/**
* 當前用戶是否具備角色
*/
@Component
public class MyAccessDesicision implements AccessDecisionManager {
/**
*
* @param authentication 當前用戶的角色回調
* @param o 獲取請求地址
* @param collection 返回值角色
* @throws AccessDeniedException
* @throws InsufficientAuthenticationException
*/
@Override
public void decide(Authentication authentication, Object o,
Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
//當前用戶具有的角色
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (ConfigAttribute configAttribute : collection){
if (configAttribute.getAttribute().equals("ROLB_LOGIN")){
//ROLB_LOGIN 判斷當前用戶是否具備角色登陸
if (authentication instanceof UsernamePasswordAuthenticationToken){
return;
}else{
throw new AccessDeniedException("權限不足,請求聯繫管理員"); //沒登陸
}
}
for (GrantedAuthority authority:authorities){
if (authority.getAuthority().equals(configAttribute.getAttribute())){
return; //角色相等
}
}
throw new AccessDeniedException("權限不足,請求聯繫管理員");
}
}