zoukankan      html  css  js  c++  java
  • Shiro在SpringBoot中的使用

    Demo代码请参考:https://github.com/roostinghawk/ShiroDemo

    以下为主要代码(经过验证,测试)

    1. pom.xml:引用shiro

           <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>${shiro.version}</version>
            </dependency>

    2. ShiroConfig(自定义config)

    import liuwei.demo.shiro.consts.Const;
    import liuwei.demo.shiro.realm.MyRealm;
    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.cache.ehcache.EhCacheManager;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
    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.CookieRememberMeManager;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.apache.shiro.web.servlet.Cookie;
    import org.apache.shiro.web.servlet.SimpleCookie;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    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.LinkedHashMap;
    import java.util.Map;
    
    @Configuration
    public class ShiroConfig {
    
        /**
         * 全局
         */
        @Bean
        public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //默认跳转到登陆页面
            shiroFilterFactoryBean.setLoginUrl("/login");
            //登陆成功后的页面
            shiroFilterFactoryBean.setSuccessUrl("/index");
            shiroFilterFactoryBean.setUnauthorizedUrl("/403");
    
            //自定义过滤器
            Map<String,Filter> filterMap=new LinkedHashMap<>();
            shiroFilterFactoryBean.setFilters(filterMap);
            //权限控制map
            Map<String,String> filterChainDefinitionMap=new LinkedHashMap<>();
            // 配置不会被拦截的链接 顺序判断
            filterChainDefinitionMap.put("/static/**", "anon");
            filterChainDefinitionMap.put("/403", "anon");
            //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
            filterChainDefinitionMap.put("/logout", "logout");
            //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->
            //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
            filterChainDefinitionMap.put("/**", "authc");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }
    
        /**
         * 核心:SecurityManager
         */
        @Bean
        public SecurityManager securityManager(DefaultWebSessionManager sessionManager){
            DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager ();
            //设置realm
            securityManager.setRealm( myRealm()  );
            securityManager.setRememberMeManager(rememberMeManager());
            securityManager.setCacheManager( ehCacheManager() );
            securityManager.setSessionManager(sessionManager);
            return securityManager;
        }
    
    
        /**
         * 身份认证Realm
         */
        @Bean
        public MyRealm myRealm(){
            MyRealm myRealm = new MyRealm();
            myRealm.setCredentialsMatcher(  hashedCredentialsMatcher() );
            return myRealm;
        }
    
        /**
         * 哈希密码比较器。在myShiroRealm中作用参数使用
         * 登陆时会比较用户输入的密码,跟数据库密码配合盐值salt解密后是否一致。
         * @return
         */
        @Bean
        public HashedCredentialsMatcher hashedCredentialsMatcher(){
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            hashedCredentialsMatcher.setHashAlgorithmName(Const.HASH_ALGORITHM);
            //散列的次数,比如散列两次,相当于 md5( md5(""));
            hashedCredentialsMatcher.setHashIterations(Const.HASH_INTERATIONS);
            return hashedCredentialsMatcher;
        }
    
    
        @Bean(name = "sessionDao")
        public EnterpriseCacheSessionDAO sessionDao(){
            EnterpriseCacheSessionDAO sessionDao = new EnterpriseCacheSessionDAO();
            sessionDao.setActiveSessionsCacheName("shiro-activeSessionCache");
            return sessionDao;
        }
    
        /**
         * Session管理Bean
         */
        @Bean(name = "sessionManager")
        public DefaultWebSessionManager sessionManager(EnterpriseCacheSessionDAO sessionDAO) {
            DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
            sessionManager.setSessionDAO(sessionDAO);
            sessionManager.setGlobalSessionTimeout(86400000);
            sessionManager.setDeleteInvalidSessions(true);
            sessionManager.setSessionValidationInterval(1800000);
            sessionManager.setSessionValidationSchedulerEnabled(true);
            Cookie cookie = new SimpleCookie("ad.es.session.id");
            cookie.setHttpOnly(Boolean.FALSE);
            cookie.setPath("/");
            sessionManager.setSessionIdCookie(cookie);
            sessionManager.setSessionIdCookieEnabled(true);
            return sessionManager;
        }
    
        /**
         *  缓存:使用Ehcache
         * @return
         */
        @Bean
        public EhCacheManager ehCacheManager(){
            EhCacheManager cacheManager=new EhCacheManager();
            cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
            return cacheManager;
        }
    
        /**
         * RememberMe
         * @return
         */
        @Bean
        public CookieRememberMeManager rememberMeManager() {
            CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
            cookieRememberMeManager.setCookie(rememberMeCookie());
            //rememberMe cookie加密的密钥  默认AES算法
    //        cookieRememberMeManager.setCipherKey();
            return  cookieRememberMeManager;
        }
    
        /**
         * cookie对象
         * @return
         */
        @Bean
        public Cookie rememberMeCookie() {
            SimpleCookie simpleCookie=new SimpleCookie("rememberMe");
            //记住我cookie生效时间,单位秒
            simpleCookie.setMaxAge(3600);
            return simpleCookie;
        }
    
    
        /**
         *  开启shiro aop注解支持.
         *  使用代理方式;所以需要开启代码支持;否则@RequiresRoles等注解无法生效
         * @param securityManager
         * @return
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
            return authorizationAttributeSourceAdvisor;
        }
    
        /**
         * Shiro生命周期处理器
         * @return
         */
        @Bean
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
            return new LifecycleBeanPostProcessor();
        }
    
        /**
         * 自动创建代理
         * @return
         */
        @Bean
        @DependsOn({"lifecycleBeanPostProcessor"})
        public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
            DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
            advisorAutoProxyCreator.setProxyTargetClass(true);
            return advisorAutoProxyCreator;
        }
    }

    3. MyRealm(自定义Realm)

    import liuwei.demo.shiro.model.Permission;
    import liuwei.demo.shiro.model.Role;
    import liuwei.demo.shiro.model.User;
    import liuwei.demo.shiro.service.UserService;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.codec.Hex;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    
    import javax.annotation.Resource;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    public class MyRealm extends AuthorizingRealm {
    
        @Resource(name = "userServiceImpl")
        private UserService userService;
    
        /**
         * 提供帐户信息,返回认证信息
         * @param authenticationToken
         * @return
         * @throws AuthenticationException
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            String loginName = (String)authenticationToken.getPrincipal();
            User user = userService.findUserByLoginName(loginName);
            if(user == null) {
                //用户不存在就抛出异常
                throw new UnknownAccountException();
            }
    
            //密码可以通过SimpleHash加密,然后保存进数据库。
            //此处是获取数据库内的账号、密码、盐值,保存到登陆信息info中
            return new SimpleAuthenticationInfo(
                    loginName,
                    user.getPassword(),
                    ByteSource.Util.bytes(Hex.decode(user.getSalt())),
                    getName());
        }
    
        /**
         * 提供用户信息,返回权限信息
         * @param principals
         * @return
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            String loginName = (String) principals.getPrimaryPrincipal();
            User user = userService.findUserByLoginName(loginName);
            List<Role> roles = userService.findRolesByUid(Integer.parseInt(user.getUid()));
            Set<String> roleSet = new HashSet<>();
            Set<String>  permissionSet = new HashSet<>();
            for(Role role : roles) {
                roleSet.add(role.getRole());
                List<Permission> permissions = userService.findPermissionsByRoleId(role.getId());
                for(Permission permission : permissions) {
                    permissionSet.add(permission.getPermission());
                }
            }
            // 将角色名称提供给授权info
            authorizationInfo.setRoles(roleSet);
            // 将权限名称提供给info
            authorizationInfo.setStringPermissions(permissionSet);
    
            return authorizationInfo;
        }
    }

    4. ehcache.xml:缓存配置(可不用)

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
             updateCheck="false">
        <diskStore path="java.io.tmpdir/demo_EhCache" />
    
        <!--
           defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
         -->
    
      
        <defaultCache
                eternal="false"
                maxElementsInMemory="1000"
                overflowToDisk="false"
                diskPersistent="false"
                timeToIdleSeconds="0"
                timeToLiveSeconds="600"
                memoryStoreEvictionPolicy="LRU" />
    
        <cache name="users"
               maxEntriesLocalHeap="200"
               timeToLiveSeconds="600">
        </cache>
    </ehcache>

    很简单,如遇到问题,请在评论回复!

    ---栖息之鹰(一个外表懒洋洋的内心有激情的程序员) 此博客为笔者原著,转载时请注明出处,谢谢!
  • 相关阅读:
    WP开发笔记——页面传参
    WP开发笔记——控件倾斜效果
    WP开发笔记——不同Item显示不同ApplicationBar:适用于Pivot与Panorama
    WP开发笔记——WP APP添加页面跳转动画
    WP开发笔记——去除 HTML 标签
    WP开发笔记——字符串 转 MD5 加密
    WP开发笔记——WP7 SDK使用技巧
    sphinx,coreseek安装
    yii2从零开始一,安装
    array_filter函数
  • 原文地址:https://www.cnblogs.com/roostinghawk/p/10719067.html
Copyright © 2011-2022 走看看