• 自定义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; } }


  • 相关阅读:
    Sqlserver 存储过程游标中调用过程,过程中包含游标提示报错
    上位机和下位机的区别是什么
    VS(visual studio)中使用ReportViewer控件和报表设计器 RDLC
    SQLServer异常捕获
    PLC(可编程逻辑控制器)
    Sqlserver中的字符串相加变成NULL
    uniapp动态更改页面标题
    如何设置打印机双面打印?
    WebService相关
    ASP.NET无刷新客户端回调(通过实现ICallbackEventHandler接口)
  • 原文地址:https://www.cnblogs.com/zeussbook/p/10778532.html
Copyright © 2020-2023  润新知