Shiro学习笔记

172 阅读2分钟

Shiro

1.shiro 的核心API

Subject :用户主体(把操作交给SecurityManger)

SecurityManger :安全管理器(关联Realm)

Realm :Shiro链接数据的桥梁

2.Springboot 整合Shiro

  • 1.shiro-spring

      <dependency>
         <groupId>org.apache.shiro</groupId>
         <artifactId>shiro-spring</artifactId>
         <version>1.4.0</version>
     </dependency>
    
  • 2.自定义Realm的类:继承AuthorizingRealm

    @Component
    public class AccountRealm extends AuthorizingRealm {
    
        @Autowired
        UserService userService;
      	//执行授权逻辑
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("执行授权方法");
    
            //给资源授权
            SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();
    
    //        //添加资源的授权字符串
    ////        info.addStringPermission("user:add");
            User user = (User) SecurityUtils.getSubject().getPrincipal();
    //        User dbuser = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getAvatar,user.getAvatar()));
            System.out.println(user.toString());
            info.addStringPermission(user.getAvatar());
    
            return info;
        }
        //执行认证逻辑
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("执行认证方法");
            //编写shiro 判断逻辑
    //        String name ="name";
    //        String password="123456";
            //1.判断用户名
            UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
    //        User user = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,token.getUsername()));
            User user = userService.getOne(new QueryWrapper<User>().eq("username", token.getUsername()));
    
            if(user==null){
                //用户名不存在
                return null;//shiro底层抛出UNknown
            }
            //判断密码
            return new SimpleAuthenticationInfo(user,user.getPassword(),"");
        }
    }
    
  • 3.编写shiro配置类

      创建3bean
    
      1.创建ShiroFilterFactoryBean(传入SecurityManger)
    
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean =new ShiroFilterFactoryBean();
            //设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //添加Shiro的内置过滤器
            Map<String, String> filterMap =new LinkedHashMap();
    //        filterMap.put("/add", "authc");
    //        filterMap.put("/update", "authc");
            filterMap.put("/login", "anon");
            filterMap.put("/test", "anon");
            filterMap.put("/getVerifyCodeImage", "anon");
    
            //授权过滤器
            filterMap.put("/add", "perms[user:add]");
            filterMap.put("/update", "perms[user:update]");
            filterMap.put("/*", "authc");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
    
            //修改调整的页面
            shiroFilterFactoryBean.setLoginUrl("/toLogin");
    
            //设置未授权提示页面
            shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
    
            return shiroFilterFactoryBean;
        }
        
     使用Shiro内置的过滤器拦截
     常用的过滤器:
        anon:无需认证可以访问
        authc:必须认证才可以访问
        user:如果使用rememberMe的功能可以直接访问
        perms:该资源必须资源权限才可以访问
        role:该资源必须得到角色权限才可以访问
        
      2.创建DefaultWebSecurityManger(传入Realm)
    
      @Bean(name="securityManager")
      public DefaultWebSecurityManager getDefaultWebSecurityManger(@Qualifier("accountRealm") AccountRealm realm) {
          DefaultWebSecurityManager securityManager =new DefaultWebSecurityManager();
          //关联Realm
          securityManager.setRealm(realm);
          return securityManager;
      }
    
      3.创建Realm的对象(自定义Realm的类)
    
  • 4.用户的登录认证

    使用Shiro编写认证
    
        @RequestMapping("/login")
        public String login(String name ,String password){
       	   1.获取Subject
            Subject subject = SecurityUtils.getSubject();
    //        2.封装用户数据
            UsernamePasswordToken token = new UsernamePasswordToken(name ,password);
            try {
               // 3.执行登录方法
                subject.login(token);
                //登录成功
                return "/test.html";
            }catch (UnknownAccountException e){
                return "redirect:/login.html";
    
            }
        }
    
  • 5.Shiro授权