springboot +shiro 详细(ehcache缓存)

1      导入maven坐标

  •   <!--shiro start-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-ehcache</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!--shiro end-->
            <!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache-core -->
            <!--本地缓存+shiro-->
            <dependency>
                <groupId>net.sf.ehcache</groupId>
                <artifactId>ehcache-core</artifactId>
                <version>2.6.11</version>
            </dependency>
    

    2   resouce 下的ehcache.xml文件

  • <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    
        <!-- 配置缓存文件夹
            默认:path="java.io.tmpdir"
             eternal="true":ture为设置缓存永不过期
             通过注解当进行增删改时清除缓存,这样就会是同步数据库的缓存了
        -->
        <diskStore path="D:\\temp"/>
    
        <defaultCache
                maxElementsInMemory="10000"
                eternal="true"
                maxElementsOnDisk="10000000"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
            <persistence strategy="localTempSwap"/>
        </defaultCache>
        <cache
                name="LL"
                maxElementsInMemory="10000"
                eternal="true"
                maxElementsOnDisk="10000000"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
            <persistence strategy="localTempSwap"/>
        </cache>
    
    </ehcache>
    

    3   shiro 配置类shiroconfig

  • package com.czxy.web.config;
    import com.czxy.web.shiro.BosCredentialsMatcher;
    import com.czxy.web.shiro.BosRealm;
    import org.apache.shiro.authc.credential.CredentialsMatcher;
    import org.apache.shiro.cache.ehcache.EhCacheManager;
    import org.apache.shiro.realm.Realm;
    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.mgt.SecurityManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * 在ShiroConfig中做什么事情呢?
     * 1 配置shiro安全管理器,向安全管理器中注入Realm域
     * 2 配置Realm域:注入密码比较器
     * 3 配置密码比较器
     * 4 配置拦截路径和放行路径
     */
    @Configuration
    public class ShiroConfig {
        /**
         * 配置安全管理器,并且注入Realm域
         *
         * @param realm
         * @return
         */
        @Bean
        public SecurityManager securityManager(Realm realm) {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(realm);
            securityManager.setCacheManager(ehCacheManager());//这个如果调用多次是同一个对象
            return securityManager;
        }
    
        /**
         * Credentials:凭证/证书 ---
         * <p>
         * 配置Realm域,注入密码比较器
         *
         * @param credentialsMatcher
         * @return
         */
        @Bean
        public BosRealm realm(CredentialsMatcher credentialsMatcher) {
            BosRealm bosRealm = new BosRealm();
            bosRealm.setCredentialsMatcher(credentialsMatcher);
            return bosRealm;
        }
    
        /**
         * 密码比较器
         *
         * @return
         */
        @Bean
        public CredentialsMatcher credentialsMatcher() {
    //    return new HashedCredentialsMatcher("MD5");
            return new BosCredentialsMatcher();
        }
    
        /**
         * 配置拦截路径和放行路径
         *
         * @param securityManager
         * @return
         */
        @Bean
        public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
            System.out.println("ShiroConfiguration.shirFilter()");
            // shiro过滤器工厂类
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    
            // 必须设置 SecurityManager
            shiroFilterFactoryBean.setSecurityManager(securityManager);
    
            //拦截器----Map集合
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
    
            //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
            filterChainDefinitionMap.put("/login*", "anon");
            filterChainDefinitionMap.put("/user/login*", "anon");
            filterChainDefinitionMap.put("/validatecode.jsp*", "anon");
            filterChainDefinitionMap.put("/css/**", "anon");
            filterChainDefinitionMap.put("/js/**", "anon");
            filterChainDefinitionMap.put("/images/**", "anon");
            filterChainDefinitionMap.put("/data/**", "anon");
    //        权限控制 粗粒度对页面进行控制
    // (放入角色也可以控制权限)
            filterChainDefinitionMap.put("/pages/base/area**", "roles[base]");
    // (放入权限也可以控制权限)
            filterChainDefinitionMap.put("/pages/base/courier**", "perms[courier:add]");
    
            //   /** 匹配所有的路径
            //  通过Map集合组成了一个拦截器链 ,自顶向下过滤,一旦匹配,则不再执行下面的过滤
            //  如果下面的定义与上面冲突,那按照了谁先定义谁说了算
            //  /** 一定要配置在最后
            filterChainDefinitionMap.put("/**", "authc");
    
            // 将拦截器链设置到shiro中
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    
    
            // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
            shiroFilterFactoryBean.setLoginUrl("/login.html");
            // 登录成功后要跳转的链接
            shiroFilterFactoryBean.setSuccessUrl("/index.html");
            //未授权界面;
            shiroFilterFactoryBean.setUnauthorizedUrl("/unauthority.html");
    
    
            return shiroFilterFactoryBean;
        }
    
        /**
         * 开启shiro aop注解支持
         * 使用代理方式;所以需要开启代码支持
         *
         * @param securityManager
         * @return
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
            return authorizationAttributeSourceAdvisor;
        }
    
    
        /**
         * 开启cglib代理
         *
         * @return
         */
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
            creator.setProxyTargetClass(true);
            return creator;
        }
    
        /**
         * ehcache 缓存
         *
         * @return
         */
        @Bean
        public EhCacheManager ehCacheManager() {
            System.out.println("ShiroConfiguration.getEhCacheManager()");
            EhCacheManager cacheManager = new EhCacheManager();
            cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
            return cacheManager;
        }
    
    }

    4 自定义ream域

  • package com.czxy.web.shiro;
    
    import com.czxy.domain.system.Permission;
    import com.czxy.domain.system.Role;
    import com.czxy.domain.system.User;
    import com.czxy.service.system.PermisionService;
    import com.czxy.service.system.RoleService;
    import com.czxy.service.system.UserService;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.util.List;
    
    public class BosRealm extends AuthorizingRealm {
        @Autowired
        private UserService userService;
        @Autowired
        private RoleService roleService;
        @Autowired
        private PermisionService permission;
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            System.out.println("授权");
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            //通过shiro 中获的用户名
            User primaryPrincipal = (User) principals.getPrimaryPrincipal();
            //通过用户名进行角色的查询
            List<Role> byUserId = roleService.findByUserId(primaryPrincipal);
            for (Role role : byUserId) {
                authorizationInfo.addRole(role.getKeyword());
            }
            //通过用户名进行查询权限
            List<Permission> permission = this.permission.findPermission(primaryPrincipal);
            for (Permission permission1 : permission) {
                authorizationInfo.addStringPermission(permission1.getKeyword());
            }
            return authorizationInfo;
        }
        //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("认证");
          UsernamePasswordToken upToken= (UsernamePasswordToken)token;
           User user = userService.QueryUserByUpToken(upToken.getUsername());
    
           if(user!=null){
               //Object principal, Object credentials, String realmName
            return new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
           }
           //表示不存在
            return null;
        }
    }
    

    5.密码比较器

  • package com.czxy.web.shiro;
    
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
    import org.apache.shiro.crypto.hash.Sha256Hash;
    
    
    public class BosCredentialsMatcher extends SimpleCredentialsMatcher {
        @Override
        public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
            System.out.println("密码比较器");
            UsernamePasswordToken upUptoken = (UsernamePasswordToken) token;
            //获取页面输入的密码
            String pwd = new String(upUptoken.getPassword());
            //对页面密码进行加密  upUptoken.getUsername撒盐
            String Rpwd = new Sha256Hash(pwd, upUptoken.getUsername(), 3).toString();
            System.out.println(Rpwd);
            //获取数据库中的密码
            String dbpwd = info.getCredentials().toString();
            return equals(Rpwd, dbpwd);
    
        }
    }
    

    6认证controller

  • package com.czxy.web.system;
    
    import com.czxy.domain.system.User;
    import com.czxy.service.system.UserService;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpSession;
    
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @GetMapping("/login")
        public ResponseEntity<String> LoginIn(User user, HttpSession httpSession) {
            try {
                // 通过shiro进行用户登录
                SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), user.getPassword()));
                //登录成功把用户名保存到session中
                User loginUser = (User) SecurityUtils.getSubject().getPrincipal();
                httpSession.setAttribute("loginUser", loginUser);
                return  new ResponseEntity<>("登录成功", HttpStatus.OK);
            } catch (Exception e) {
                return new ResponseEntity<>("登录失败",HttpStatus.INTERNAL_SERVER_ERROR);
            }
    
        }
        @GetMapping("/logout")
        public ResponseEntity<String> Loginout( HttpSession httpSession) {
            httpSession.removeAttribute("loginUser");
            SecurityUtils.getSubject().logout();
        return  new ResponseEntity<>(HttpStatus.OK);
        }
    
    }
    

    7 授权controller

  • package com.czxy.web.system;
    
    import com.czxy.domain.system.Menu;
    import com.czxy.domain.system.User;
    import com.czxy.domain.vo.DataGridResult;
    import com.czxy.service.system.MenuService;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/menu")
    public class ShowMenuController {
        @Autowired
        private MenuService menuService;
    
    
        @GetMapping
        @RequestMapping("/showMenu")
        public ResponseEntity<List<Menu>> showMent(){
          User user = (User) SecurityUtils.getSubject().getPrincipal();
           List<Menu> list= menuService.findMenuByUser(user);
           return new ResponseEntity<>(list,HttpStatus.OK);
        }
    }
    

猜你喜欢

转载自blog.csdn.net/qq_42917455/article/details/84196181