自定義shiro實現權限驗證方法isAccessAllowed


由於Shiro filterChainDefinitions中 roles默認是and, admin= user,roles[system,general] 
比如:roles[system,general] ,表示同時需要“system”和“general” 2個角色(權限)才通過認證,缺一不可。
但是在實際業務中,一個端口往往同時對幾個角色開放。比如管理員賬號擁有訪問所有端口的權限。那么此時的and顯然是不合時宜的,與之替代的是or

一、重新實現AuthorizationFilter類
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * @Auther: lanhaifeng
 * @Date: 2019/4/18 0018 17:40
 * @Description:支持多角色驗證
 * 由於Shiro filterChainDefinitions中 roles默認是and,
 * = user,roles[system,general]
 * 比如:roles[system,general] ,表示同時需要“system”和“general” 2個角色才通過認證
 * 但是在實際業務中,一個端口的權限往往對多個角色開放(比如管理員可以使用一切權利)
 */
public class MyRolesAuthorizationFilter extends AuthorizationFilter{

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
            throws Exception {
        Subject subject = getSubject(request, response);
        String[] rolesArray = (String[]) mappedValue;
        //沒有權限訪問
        if (rolesArray == null || rolesArray.length == 0) {
            return true;
        }
        for (int i = 0; i < rolesArray.length; i++) {
            //若當前用戶是rolesArray中的任何一個,則有權限訪問
            if (subject.hasRole(rolesArray[i])) {
                return true;
            }
        }
        return false;
    }
}

 

二、在ShiroConfig引用,其實spring boot集成shiro也就這兩步,加上自定義權限驗證 和自定義登錄驗證。

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shirFilter(DefaultWebSecurityManager securityManager) {
        //System.out.println("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //添加自定義驗證方法,注意這個Filter繼承javax.servlet.Filter
        Map<String, Filter> filterMap=new HashMap<>();
        filterMap.put("rolesOr",roleFilter());
        shiroFilterFactoryBean.setFilters(filterMap);
        //攔截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        // 配置不會被攔截的鏈接 順序判斷
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/gif/**", "anon");
        //配置退出 過濾器,其中的具體的退出代碼Shiro已經替我們實現了
        filterChainDefinitionMap.put("/sanyi/logout", "logout");
        //<!-- 過濾鏈定義,從上向下順序執行,一般將/**放在最為下邊 -->:這是一個坑呢,一不小心代碼就不好使了;
        //<!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問-->
        filterChainDefinitionMap.put("/sanyi/index", "anon");/*swagger*/
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        /*business業務端(1管理員,3業務員)*/
        filterChainDefinitionMap.put("/contract/base/**", "authc,rolesOr[1,3]");
     /*其他,一定要采取白名單*/ filterChainDefinitionMap.put("/**", "authc"); // 如果不設置默認會自動尋找Web工程根目錄下的"/login"頁面 shiroFilterFactoryBean.setLoginUrl("/sanyi/index"); // 登錄成功后要跳轉的鏈接 shiroFilterFactoryBean.setSuccessUrl("/"); //未授權界面; shiroFilterFactoryBean.setUnauthorizedUrl("/sanyi/nopermission"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public MyRolesAuthorizationFilter roleFilter(){ MyRolesAuthorizationFilter roleFilter=new MyRolesAuthorizationFilter(); return roleFilter; } /** * 密碼憑證匹配器 * (由於我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了 * ) * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:這里使用MD5算法; hashedCredentialsMatcher.setHashIterations(10);//散列的次數10哈哈; return hashedCredentialsMatcher; } /** * 身份認證realm; (這個需要自己寫,賬號密碼校驗;權限等) * @return */ @Bean public MyShiroRealm myShiroRealm(){ MyShiroRealm myShiroRealm = new MyShiroRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } /** * 會話管理器 * @return */ @Bean public DefaultWebSessionManager sessionManager(){ DefaultWebSessionManager sessionManager=new DefaultWebSessionManager(); sessionManager.setGlobalSessionTimeout(1800000);//單位是ms return sessionManager; } @Bean public DefaultWebSecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); securityManager.setSessionManager(sessionManager()); return securityManager; } /** * 開啟shiro aop注解支持. * 使用代理方式;所以需要開啟代碼支持; * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean(name="simpleMappingExceptionResolver") public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() { SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); mappings.setProperty("DatabaseException", "databaseError");//數據庫異常處理 mappings.setProperty("UnauthorizedException","403"); r.setExceptionMappings(mappings); // None by default r.setDefaultErrorView("error"); // No default r.setExceptionAttribute("exception"); // Default is "exception" //r.setWarnLogCategory("example.MvcLogger"); // No default return r; } }

 

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM