Shiro-Springboot

  • 1、shiro配置类:

package com.zhibi.xiuba.mgr.conf.shiro; 

import org.apache.shiro.authc.credential.HashedCredentialsMatcher; 
import org.apache.shiro.authc.pam.AuthenticationStrategy; 
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy; 
import org.apache.shiro.authz.ModularRealmAuthorizer; 
import org.apache.shiro.cache.ehcache.EhCacheManager; 
import org.apache.shiro.realm.Realm; 
import org.apache.shiro.session.mgt.eis.SessionDAO; 
import org.apache.shiro.spring.LifecycleBeanPostProcessor; 
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.servlet.Cookie; 
import org.apache.shiro.web.servlet.ShiroHttpSession; 
import org.apache.shiro.web.servlet.SimpleCookie; 
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; 
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.DependsOn; 

import javax.servlet.Filter; 
import java.util.*; 

/** 
* Shiro 配置 
* Apache Shiro 核心通过 Filter 来实现,就好像SpringMvc 通过DispachServlet 来主控制一样。 
* 既然是使用 Filter 一般也就能猜到,是通过URL规则来进行过滤和权限校验,所以我们需要定义一系列关于URL的规则和访问权限。 
*/ 
@Configuration 
public class ShiroConfiguration { 

    private Logger logger = LoggerFactory.getLogger(this.getClass()); 


    /** 
    * 凭证匹配器 
    * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 
    * 所以我们需要修改下doGetAuthenticationInfo中的代码; 
    * ) 
    * 
    * @return 
    */ 
    @Bean(name = "adminHashedCredentialsMatcher") 
    public HashedCredentialsMatcher adminHashedCredentialsMatcher() { 
        logger.info("ShiroConfiguration.adminHashedCredentialsMatcher()"); 
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); 
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; 
        hashedCredentialsMatcher.setHashIterations(2);//散列的次数,当于 m比如散列两次,相d5(md5("")); 
        return hashedCredentialsMatcher; 
    } 

    @Bean(name = "customHashedCredentialsMatcher") 
    public HashedCredentialsMatcher customHashedCredentialsMatcher() { 
        logger.info("ShiroConfiguration.adminHashedCredentialsMatcher()"); 
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); 
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; 
        hashedCredentialsMatcher.setHashIterations(1);//散列的次数,当于 m比如散列两次,相d5(md5("")); 
        return hashedCredentialsMatcher; 
    } 

    /** 
    * 前台身份认证realm; 
    * 
    * @return 
    */ 
    @Bean(name = "customShiroRealm") 
    public CustomShiroRealm customShiroRealm() { 
        logger.info("ShiroConfiguration.customShiroRealm()"); 
        CustomShiroRealm customShiroRealm = new CustomShiroRealm(); 
        customShiroRealm.setCredentialsMatcher(customHashedCredentialsMatcher()); 
        return customShiroRealm; 
    } 

    /** 
    * 后台身份认证realm; 
    * 
    * @return 
    */ 
    @Bean(name = "adminShiroRealm") 
    public AdminShiroRealm adminShiroRealm() { 
        logger.info("ShiroConfiguration.adminShiroRealm()"); 
        AdminShiroRealm adminShiroRealm = new AdminShiroRealm(); 
        adminShiroRealm.setCredentialsMatcher(adminHashedCredentialsMatcher()); 
        return adminShiroRealm; 
    } 

    /** 
    * shiro缓存管理器; 
    * 需要注入对应的其它的实体类中: 
    * 1、安全管理器:securityManager 
    * 可见securityManager是整个shiro的核心; 
    * 
    * @return 
    */ 
    @Bean(name = "ehCacheManager") 
    public EhCacheManager ehCacheManager() { 
        logger.info("ShiroConfiguration.ehCacheManager()"); 
        EhCacheManager cacheManager = new EhCacheManager(); 
        cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml"); 
        return cacheManager; 
    } 


    /** 
    * Shiro默认提供了三种 AuthenticationStrategy 实现: 
    * AtLeastOneSuccessfulStrategy :其中一个通过则成功。 
    * FirstSuccessfulStrategy :其中一个通过则成功,但只返回第一个通过的Realm提供的验证信息。 
    * AllSuccessfulStrategy :凡是配置到应用中的Realm都必须全部通过。 
    * authenticationStrategy 
    * 
    * @return 
    */ 
    @Bean(name = "authenticationStrategy") 
    public AuthenticationStrategy authenticationStrategy() { 
        logger.info("ShiroConfiguration.authenticationStrategy()"); 
        return new FirstSuccessfulStrategy(); 
    } 

    /** 
    * @return 
    * @see DefaultWebSessionManager 
    */ 
    @Bean(name = "sessionManager") 
    public DefaultWebSessionManager defaultWebSessionManager() { 
        logger.info("ShiroConfiguration.defaultWebSessionManager()"); 
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); 
        sessionManager.setSessionDAO(redisSessionDAO()); 
        sessionManager.setCacheManager(ehCacheManager()); 
        //单位为毫秒(1秒=1000毫秒) 3600000毫秒为1个小时 
        sessionManager.setSessionValidationInterval(3600000 * 12); 
        //3600000 milliseconds = 1 hour 
        sessionManager.setGlobalSessionTimeout(3600000 * 12); 
        sessionManager.setDeleteInvalidSessions(true); 
        sessionManager.setSessionValidationSchedulerEnabled(true); 
        Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME); 
        cookie.setName("WEBID"); 
        cookie.setHttpOnly(true); 
        sessionManager.setSessionIdCookie(cookie); 
        return sessionManager; 
    } 

    @Bean 
    public SessionDAO redisSessionDAO() { 
        RedisSessionDAO sessionDAO = new RedisSessionDAO(); 
        return sessionDAO; 

    } 

    /** 
    * @return 
    * @see org.apache.shiro.mgt.SecurityManager 
    */ 
    @Bean(name = "securityManager") 
    public DefaultWebSecurityManager getDefaultWebSecurityManage() { 
        logger.info("ShiroConfiguration.getDefaultWebSecurityManage()"); 
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 

        Map<String, Object> shiroAuthenticatorRealms = new HashMap<>(); 
        shiroAuthenticatorRealms.put("adminShiroRealm", adminShiroRealm()); 
        shiroAuthenticatorRealms.put("customShiroRealm", customShiroRealm()); 

        Collection<Realm> shiroAuthorizerRealms = new ArrayList<Realm>(); 
        shiroAuthorizerRealms.add(adminShiroRealm()); 
        shiroAuthorizerRealms.add(customShiroRealm()); 

        CustomModularRealmAuthenticator customModularRealmAuthenticator = new CustomModularRealmAuthenticator(); 
        customModularRealmAuthenticator.setDefinedRealms(shiroAuthenticatorRealms); 
        customModularRealmAuthenticator.setAuthenticationStrategy(authenticationStrategy()); 
        securityManager.setAuthenticator(customModularRealmAuthenticator); 
        ModularRealmAuthorizer customModularRealmAuthorizer = new ModularRealmAuthorizer(); 
        customModularRealmAuthorizer.setRealms(shiroAuthorizerRealms); 
        securityManager.setAuthorizer(customModularRealmAuthorizer); 
        //设置realm. 
        //securityManager.setRealm(adminShiroRealm()); 
        //securityManager.setRealm(customShiroRealm()); 
        //注入缓存管理器; 
        securityManager.setCacheManager(ehCacheManager());//这个如果执行多次,也是同样的一个对象; 
        securityManager.setSessionManager(defaultWebSessionManager()); 
        return securityManager; 
    } 

    /** 
    * 开启shiro aop注解支持. 
    * 使用代理方式;所以需要开启代码支持; 
    * 
    * @param securityManager 
    * @return 
    */ 
    @Bean(name = "authorizationAttributeSourceAdvisor") 
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { 
        logger.info("ShiroConfiguration.authorizationAttributeSourceAdvisor()"); 
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); 
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); 
        return authorizationAttributeSourceAdvisor; 
    } 

    /** 
    * ShiroFilterFactoryBean 处理拦截资源文件问题。 
    * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在 
    * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager 
    * Filter Chain定义说明 
    * 1、一个URL可以配置多个Filter,使用逗号分隔 
    * 2、当设置多个过滤器时,全部验证通过,才视为通过 
    * 3、部分过滤器可指定参数,如perms,roles 
    */ 
    @Bean(name = "shiroFilter") 
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) { 
        logger.info("ShiroConfiguration.shiroFilter()"); 
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 
        // 必须设置 SecurityManager 
        shiroFilterFactoryBean.setSecurityManager(securityManager); 
        //增加自定义过滤 
        Map<String, Filter> filters = new HashMap<>(); 
        filters.put("admin", new AdminFormAuthenticationFilter()); 
        filters.put("custom", new CustomFormAuthenticationFilter()); 
        shiroFilterFactoryBean.setFilters(filters); 
        //拦截器. 
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); 

        //配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了 
        /** 
        * anon(匿名)org.apache.shiro.web.filter.authc.AnonymousFilter 
        * authc(身份验证)org.apache.shiro.web.filter.authc.FormAuthenticationFilter 
        * authcBasic(http基本验证)org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter 
        * logout(退出)org.apache.shiro.web.filter.authc.LogoutFilter 
        * noSessionCreation(不创建session) org.apache.shiro.web.filter.session.NoSessionCreationFilter 
        * perms(许可验证)  org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter 
        * port(端口验证)org.apache.shiro.web.filter.authz.PortFilter 
        * rest  (rest方面)  org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter 
        * roles(权限验证)org.apache.shiro.web.filter.authz.RolesAuthorizationFilter 
        * ssl (ssl方面)org.apache.shiro.web.filter.authz.SslFilter 
        * member (用户方面)org.apache.shiro.web.filter.authc.UserFilter 
        * user表示用户不一定已通过认证,只要曾被Shiro记住过登录状态的用户就可以正常发起请求,比如rememberMe 
        */ 

        //<!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; 
        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> 
        filterChainDefinitionMap.put("/**/login", "anon"); 
        filterChainDefinitionMap.put("/console/dashboard/zhu/**", "anon"); 
        filterChainDefinitionMap.put("/console/dashboard/phone/**", "anon"); 
        filterChainDefinitionMap.put("/**/logout", "logout"); 
        filterChainDefinitionMap.put("/member/reg", "anon"); 
        //配置记住我或认证通过可以访问的地址 
        filterChainDefinitionMap.put("/console/**", "admin"); 
        filterChainDefinitionMap.put("/member/**", "custom"); 
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 
        //shiroFilterFactoryBean.setLoginUrl("/member/login"); 
        // 登录成功后要跳转的链接 
        //shiroFilterFactoryBean.setSuccessUrl("/member/index"); 
        //未授权界面; 
        //shiroFilterFactoryBean.setUnauthorizedUrl("/console/403"); 
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 
        return shiroFilterFactoryBean; 
    } 

    /** 
    * 注入LifecycleBeanPostProcessor 
    * 
    * @return 
    */ 
    @Bean(name = "lifecycleBeanPostProcessor") 
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { 
        logger.info("ShiroConfiguration.lifecycleBeanPostProcessor()"); 
        return new LifecycleBeanPostProcessor(); 
    } 

    @ConditionalOnMissingBean 
    @Bean(name = "defaultAdvisorAutoProxyCreator") 
    @DependsOn("lifecycleBeanPostProcessor") 
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() { 
        logger.info("ShiroConfiguration.getDefaultAdvisorAutoProxyCreator()"); 
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); 
        daap.setProxyTargetClass(true); 
        return daap; 
    } 
} 

  • 2、假设现在有这样一种需求:存在两张表user和admin,分别记录普通用户和管理员的信息。并且现在要实现普通用户和管理员的分开登录,即需要两个Realm——UserRealm和AdminRealm,分别处理普通用户和管理员的验证功能。
    但是正常情况下,当定义了两个Realm,无论是普通用户登录,还是管理员登录,都会由这两个Realm共同处理。这是因为,当配置了多个Realm时,我们通常使用的认证器是shiro自带的org.apache.shiro.authc.pam.ModularRealmAuthenticator,

package com.zhibi.xiuba.mgr.conf.shiro; 

import org.apache.shiro.ShiroException; 
import org.apache.shiro.authc.AuthenticationException; 
import org.apache.shiro.authc.AuthenticationInfo; 
import org.apache.shiro.authc.AuthenticationToken; 
import org.apache.shiro.authc.pam.ModularRealmAuthenticator; 
import org.apache.shiro.realm.Realm; 
import org.apache.shiro.util.CollectionUtils; 

import java.util.Collection; 
import java.util.Map; 

public class CustomModularRealmAuthenticator extends ModularRealmAuthenticator { 

    private Map<String, Object> definedRealms; 

    /** 
    * 多个realm实现 
    */ 
    @Override 
    protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) { 
        return super.doMultiRealmAuthentication(realms, token); 
    } 

    /** 
    * 调用单个realm执行操作 
    */ 
    @Override 
    protected AuthenticationInfo doSingleRealmAuthentication(Realm realm,AuthenticationToken token) { 

        // 如果该realms不支持(不能验证)当前token 
        if (!realm.supports(token)) { 
        throw new ShiroException("token错误!"); 
        } 
        AuthenticationInfo info = null; 
        try { 
        info = realm.getAuthenticationInfo(token); 
        if (info == null) { 
        throw new ShiroException("token不存在!"); 
        } 
        } catch (Exception e) { 
        throw new ShiroException("用户名或者密码错误!"); 
        } 
        return info; 
    } 


    /** 
    * 判断登录类型执行操作     
    */ 
    @Override 
    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)throws AuthenticationException { 
        this.assertRealmsConfigured(); 
        Realm realm = null; 
        CustomerAuthenticationToken token = (CustomerAuthenticationToken) authenticationToken; 
        //判断是否是后台用户 

        if ("1".equals(token.getLoginType())) { 
        realm = (Realm) this.definedRealms.get("customShiroRealm"); 
        }else{ 
        realm = (Realm) this.definedRealms.get("adminShiroRealm"); 
        } 

        return this.doSingleRealmAuthentication(realm, authenticationToken); 
    } 

    /** 
    * 判断realm是否为空 
    */ 
    @Override 
    protected void assertRealmsConfigured() throws IllegalStateException { 
        this.definedRealms = this.getDefinedRealms(); 
        if (CollectionUtils.isEmpty(this.definedRealms)) { 
        throw new ShiroException("值传递错误!"); 
        } 
        } 

        public Map<String, Object> getDefinedRealms() { 
        return this.definedRealms; 
        } 

    public void setDefinedRealms(Map<String, Object> definedRealms) { 
        this.definedRealms = definedRealms; 
    } 

} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
课程简介:历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值