美文网首页
跟我学shiro——springboot集成shiro

跟我学shiro——springboot集成shiro

作者: 书眉间_清风 | 来源:发表于2018-10-23 11:50 被阅读0次

    准备工作

     <dependency>
       <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-all</artifactId>
     <version>1.2.5</version>
    </dependency>
    <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.3.2</version>
    </dependency>
    

    1:创建ShiroConfigBean

    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.cache.ehcache.EhCacheManager;
    import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    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;
    
    @Configuration
    public class ShiroConfigBean {
     
        @Bean
        public ShiroFilterFactoryBean shirFilter(DefaultWebSecurityManager securityManager) {
            System.out.println("初始化拦截器");
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            // 必须设置 SecurityManager
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            // 拦截器.
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
            // 设置login URL
            shiroFilterFactoryBean.setLoginUrl("/login");
            //游客,开发权限
            filterChainDefinitionMap.put("/guest/**", "anon");
            //用户,需要角色权限 “user”
            filterChainDefinitionMap.put("/user/**", "roles[user]");
            //管理员,需要角色权限 “admin”
            filterChainDefinitionMap.put("/admin/**", "roles[admin]");
            //开放登陆接口
            filterChainDefinitionMap.put("/login", "anon");
            //其余接口一律拦截
            //主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截
            filterChainDefinitionMap.put("/**", "authc");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }
     
        /*
         * 凭证匹配器 (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
         * 所以我们需要修改下doGetAuthenticationInfo中的代码; )
         */
        @Bean
        public HashedCredentialsMatcher hashedCredentialsMatcher() {
            System.out.println("密码匹配器");
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
            hashedCredentialsMatcher.setHashIterations(1);// 散列的次数,比如散列两次,相当于md5(md5(""));
            return hashedCredentialsMatcher;
        }
    //
        @Bean
        public MyShiroRealm myShiroRealm() {
            System.out.println("进入relam");
            MyShiroRealm myShiroRealm = new MyShiroRealm();
            myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
            return myShiroRealm;
        }
     
        @Bean
        public DefaultWebSecurityManager securityManager() {
            System.out.println("将relam注入到securityManager");
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 注入自定义的realm;
            securityManager.setRealm(myShiroRealm());
            // 注入缓存管理器;
            securityManager.setCacheManager(ehCacheManager());
    
            return securityManager;
        }
     
        /*
         * 开启shiro aop注解支持 使用代理方式;所以需要开启代码支持;
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
                DefaultWebSecurityManager securityManager) {
            System.out.println("开启注解模式");
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
            return authorizationAttributeSourceAdvisor;
        }
     
        /**
         * DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
         */
        @Bean
        @ConditionalOnMissingBean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
            defaultAAP.setProxyTargetClass(true);
            return defaultAAP;
        }
     
        /*
         * shiro缓存管理器;
         * 需要注入对应的其它的实体类中-->安全管理器:securityManager可见securityManager是整个shiro的核心;
         */
        @Bean
        public EhCacheManager ehCacheManager() {
            System.out.println("shiro缓存");
            EhCacheManager cacheManager = new EhCacheManager();
            cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
            return cacheManager;
        }
    }
    
    

    2:编写自定义的realm

    import com.tuyue.entity.User;
    import com.tuyue.mapper.PermissionMapper;
    import com.tuyue.mapper.RoleMapper;
    import com.tuyue.mapper.UserMapper;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    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.apache.shiro.util.ByteSource;
    
    import org.apache.shiro.util.StringUtils;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.context.annotation.Bean;
    
    /**
     * realm实现类,用于实现具体的验证和授权方法
     * @author Bean
     *
     */
    public class MyShiroRealm extends AuthorizingRealm {
     @Autowired
     private UserMapper userMapper;
     @Autowired
     private RoleMapper roleMapper;
     @Autowired
     private PermissionMapper permissionMapper;
        /**
         * 方面用于加密 参数:AuthenticationToken是从表单穿过来封装好的对象
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("开始验证是否登录" + token.getPrincipal());
            UsernamePasswordToken upToken = (UsernamePasswordToken) token;
            // 获得从表单传过来的用户名
            String username = upToken.getUsername();
            if(username==null||username.length()==0){
                return null;
            }
            User user=new User();
            user.setUsername(username);
            User user1 = userMapper.selectOne(user);
            // 如果用户不存在,抛此异常
            if (user1==null) {
                throw new UnknownAccountException("无此用户名!");
            }
            // 认证的实体信息,可以是username,也可以是用户的实体类对象,这里用的用户名
            Object principal = user1;
            // 颜值加密的颜,可以用用户名
            ByteSource credentialsSalt = ByteSource.Util.bytes("222");
            // 当前realm对象的名称,调用分类的getName()
            String realmName = this.getName();
            // 创建SimpleAuthenticationInfo对象,并且把username和password等信息封装到里面用户密码的比对是Shiro帮我们完成的
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, user1.getPassword(),credentialsSalt, realmName);
            return info;
        }
    
        @Bean
        @ConditionalOnMissingBean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
            defaultAAP.setProxyTargetClass(true);
            return defaultAAP;
        }
     
        // 用于授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            System.out.println("授权方法执行");
            Set<String> roles = new HashSet<>();
            Set<String> permissions = new HashSet<>();
            User user= (User) principals.getPrimaryPrincipal();
            List<String> list = roleMapper.selectByUserId(user.getId());
            for (String s : list) {
                roles.add(s);
            }
            List<String> list1 = permissionMapper.selectByuserId(user.getId());
            for (String s : list1) {
                permissions.add(s);
            }
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
            //添加权限
            info.setStringPermissions(permissions);
            return info;
        }
    }
    
    

    3:创建数据库

    USE `shiro`;
    
    /*Table structure for table `permission` */
    
    DROP TABLE IF EXISTS `permission`;
    
    CREATE TABLE `permission` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `permission_name` varchar(20) DEFAULT NULL,
      `source` varchar(20) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
    
    /*Data for the table `permission` */
    
    insert  into `permission`(`id`,`permission_name`,`source`) values (1,'添加用户','user:save'),(2,'删除用户','user:del'),(3,'修改用户','user:up'),(4,'添加商品','goods:save'),(5,'修改商品','goods:up'),(6,'删除商品','goods:del');
    
    /*Table structure for table `permission_role` */
    
    DROP TABLE IF EXISTS `permission_role`;
    
    CREATE TABLE `permission_role` (
      `permission_id` int(11) DEFAULT NULL,
      `role_id` int(11) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    /*Data for the table `permission_role` */
    
    insert  into `permission_role`(`permission_id`,`role_id`) values (1,1),(2,1),(3,1),(4,2),(5,2),(6,2);
    
    /*Table structure for table `role` */
    
    DROP TABLE IF EXISTS `role`;
    
    CREATE TABLE `role` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `role_name` varchar(25) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    /*Data for the table `role` */
    
    insert  into `role`(`id`,`role_name`) values (1,'用户管理员'),(2,'商品管理员');
    
    /*Table structure for table `user` */
    
    DROP TABLE IF EXISTS `user`;
    
    CREATE TABLE `user` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `username` varchar(20) DEFAULT NULL,
      `password` varchar(100) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    /*Data for the table `user` */
    
    insert  into `user`(`id`,`username`,`password`) values (1,'123','c26a263602b986958afab92363c5984f'),(2,'456','456');
    
    /*Table structure for table `user_role` */
    
    DROP TABLE IF EXISTS `user_role`;
    
    CREATE TABLE `user_role` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `user_id` int(11) DEFAULT NULL,
      `role_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    /*Data for the table `user_role` */
    
    insert  into `user_role`(`id`,`user_id`,`role_id`) values (1,1,1),(2,2,2);
    

    4:编写controller进行测试
    (1)先测试登录

      @RequestMapping("/login")
        public String loginUser(String username,String password) {
            UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
            Subject subject = SecurityUtils.getSubject();
            try {
                subject.login(usernamePasswordToken);   //完成登录
                boolean aaa = subject.hasRole("用户管理员");
                System.out.println("2222"+aaa);
                return "登录成功";
            } catch(Exception e) {
                e.printStackTrace();
                return "登陆失败";
            }
            
        }
    

    (2) 测试权限

    @RequestMapping("test")
        @RequiresAuthentication
        @RequiresPermissions("user:del")
        public String test() {
            Subject subject = SecurityUtils.getSubject();
            return "当前对象:"+subject.getPrincipal().toString();
        }
    

    相关文章

      网友评论

          本文标题:跟我学shiro——springboot集成shiro

          本文链接:https://www.haomeiwen.com/subject/jppozftx.html