溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用SpringSecurity實(shí)現(xiàn)動(dòng)態(tài)加載權(quán)限信息

發(fā)布時(shí)間:2022-01-05 17:25:04 來源:億速云 閱讀:159 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要介紹了如何使用SpringSecurity實(shí)現(xiàn)動(dòng)態(tài)加載權(quán)限信息,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

①數(shù)據(jù)庫中資源與角色對(duì)應(yīng)關(guān)系,以及角色和用戶對(duì)應(yīng)關(guān)系如下圖所示:

如何使用SpringSecurity實(shí)現(xiàn)動(dòng)態(tài)加載權(quán)限信息

 ②實(shí)現(xiàn)FilterInvocationSecurityMetadataSource類

(1)List<Menu> menus = menuService.getMenusWithRoles();這個(gè)是你自己的資源對(duì)應(yīng)角色的查詢方法。

(2)重寫的support方法都返回true

@Configuration
public class MyFilterInvocation implements FilterInvocationSecurityMetadataSource {
 
    @Autowired
    private MenuService menuService;
 
    AntPathMatcher antPathMatcher = new AntPathMatcher();
 
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        String requestUrl = ((FilterInvocation) object).getRequestUrl();
        List<Menu> menus = menuService.getMenusWithRoles();
        //- 遍歷數(shù)據(jù)庫的url,看請(qǐng)求路徑是否與其匹配
        for (Menu menu : menus) {
            //- 如果請(qǐng)求路徑和數(shù)據(jù)庫的路徑匹配
            if (antPathMatcher.match(menu.getUrl(),requestUrl)){
                //- 訪問該路徑需要的角色
                List<Role> roles = menu.getRoles();
                String[] strs = new String[roles.size()];
                for (int i = 0; i < roles.size(); i++) {
                    strs[i] = roles.get(i).getName();
                }
                return SecurityConfig.createList(strs);
            }
        }
        //- 如果請(qǐng)求路徑和數(shù)據(jù)庫的所有路徑都不匹配,說明這個(gè)資源是登錄后即可訪問的
        //- 用戶登錄即可訪問,相當(dāng)于在SecurityConfig中配置了.anyRequest().authenticated()
        return SecurityConfig.createList("ROLE_LOGIN");
    }
 
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }
 
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}

③實(shí)現(xiàn)AccessDecisionManager

重寫的support方法都返回true

@Configuration
public class MyDecisionManager implements AccessDecisionManager {
 
 
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        for (ConfigAttribute configAttribute : configAttributes) {
            String needRole = configAttribute.getAttribute();
            if ("ROLE_LOGIN".equals(needRole)) {
                //- 用戶登錄即可訪問,相當(dāng)于在SecurityConfig中配置了.anyRequest().authenticated()
                if (authentication instanceof AnonymousAuthenticationToken) {
                    throw new AccessDeniedException("尚未登錄,請(qǐng)先登錄");
                } else {
                    return;
                }
            }
            
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            //這里我寫的是只要訪問該資源的用戶具有`訪問該資源所需要角色`的其中一個(gè)即可
            for (GrantedAuthority authority : authorities) {
                if (authority.getAuthority().equals(needRole)) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("權(quán)限不足,請(qǐng)聯(lián)系管理員");
    }
 
    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }
 
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}

④到SecurityConfig配置類中完成相應(yīng)配置

@Autowired
    private MyDecisionManager myDecisionManager;
    
    @Autowired
    private  MyFilterInvocation myFilterInvocation;
 
     @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setAccessDecisionManager(myDecisionManager);
                        object.setSecurityMetadataSource(myFilterInvocation);
                        return object;
                    }
                });
 
            http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler());
 
    }
 
 
    @Bean
    MyAccessDeniedHandler myAccessDeniedHandler(){
        return new MyAccessDeniedHandler();
    }

⑤可選,實(shí)現(xiàn)AccessDeniedHandler

public class MyAccessDenied implements AccessDeniedHandler {
 
    @Override
    public void handle(HttpServletRequest req, HttpServletResponse resp, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter pw = resp.getWriter();
        pw.write(new ObjectMapper().writeValueAsString(RespBean.error("權(quán)限不夠,請(qǐng)聯(lián)系管理員")));
        pw.flush();
        pw.close();
    }
}

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“如何使用SpringSecurity實(shí)現(xiàn)動(dòng)態(tài)加載權(quán)限信息”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI