正在加载中,请稍后

Shiro

Springboot+Shiro

image

Shiro的功能

认证,授权、加密、会话管理、与Web项目集成、缓存等

Shiro的三大核心组件

Subject:当前用户(所有的Subject实例都被绑定在一个SecurityManager上)

SecurityManager:用于管理所有的Subject,Shiro的架构核心,用来协调内部各安全组件,管理内部组件实例,并通过它来提供各种安全管理服务。

Realm:域,相当对存储了用户权限信息和身份信息等数据,供SecurManager安全管理。

Shiro是怎样运行的

应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager,我们需要给SecurityManager注入Realm,从而让Security对Subject进行判断是否合法用户及权限。

Authentication和Authorization:

Authentication:负责验证用户身份

Authorization:负责授权访问控制,对当前用户操作进行认证授权,证明该用户有当前操作的权限

其他组件

SessionManager:Shiro为任何应用提供了一个会话编程范式

CacheManager:对Shiro的其他组件提供缓存支持

Shiro的优点:

不跟任何框架绑定,可以独立运行

加密简单,身份认证简单,支持多种数据源

对角色授权简单,支持细粒度的授权(方法级)

支持缓存,以提升应用程序性能

SpringSecurity和shiro的比较

相比SpringSecurity,Shiro在保持功能强大的同时,使用简单,灵活,同时配置少,容易上手。

SpringSecurity必须在Spring的环境才能使用,Shiro在javaSe环境就可以

Shiro实现认证过程

public class AuthRealm extends AuthorizingRealm {}
Shiro的认证是由Realm执行的,SecurityManager会调用Realm的doGetAuthenticationInfo()方法,进行用户认证


 @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行认证逻辑");
        /**
         * 判断ShiroRealm逻辑UsernamePasswordToken是否正确
         */
        //1判断用户名
        UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken)authenticationToken;
        User user=userService.findByname(usernamePasswordToken.getUsername());
        if(user==null){
            //用户名不存在
            return null;
        }
        //判断密码是否正确
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }

@RequestMapping("/login")
      public String login(User user, Model model) {
          /**
           *使用shiro编写认证操作
           */
          //1:获取subject
         Subject subject = SecurityUtils.getSubject();
         //2:封装用户账号和密码
         UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUsername(), user.getPassword());
         //3:执行登录方法
         try {
             subject.login(usernamePasswordToken);
             model.addAttribute(user);
             //登录成功
             //成功后跳转到
             //return "redirect:/test";
             return "/test";
         } catch (UnknownAccountException e) {
             //e.printStackTrace();
             //登录失败用户名不存在
             model.addAttribute("msg","用户名不存在");
             return "login";
         }catch (IncorrectCredentialsException e){
             //登录失败密码错误
             model.addAttribute("msg","密码错误");
             return "login";
         }
     }
 }

Shiro实现授权的过程

SecurityManager会调用Realm的doGetAuthorizationInfo()方法进行角色的授权的验证。

@Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权逻辑");
        /**
         * 给资源授权
         */
        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
         //添加授权字符串
        //simpleAuthorizationInfo.addStringPermission("user:add");

        //--------------------认证账号
        Subject subject= SecurityUtils.getSubject();
        User user=(User)subject.getPrincipal();
        User user1=userService.findById(user.getId());
        if(user1==null){
            //用户名不存在
            return null;
        }
        //-------------------开始授权
        List<Permission> permissions =permissionService.getPermissionByUserId(user1.getId());
        for (Permission per : permissions) {
            simpleAuthorizationInfo.addStringPermission(per.getName());
            System.out.println("拥有权限:"+per.getName());
        }
        return simpleAuthorizationInfo;
    }

ShiroConfiguration的配置过程

1.创建Ream,标识为Bean

@Bean("userRealm")
     public UserRealm getRealm(){
         UserRealm userRealm=new UserRealm();
         return userRealm;
     }

2.创建DefaultWebSecurityManager,标识为Bean,并且与Realm绑定

@Bean("securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
         DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
         //关联Realm
         securityManager.setRealm(userRealm);
         return securityManager;
     }

3.创建ShiroFulterFactoryBean,标识为Bean,将manager对象传入,再将manager设置为安全管理器,最后设置拦截的filterMap

@Bean
     public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
         ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
         //设置安全管理器
         shiroFilterFactoryBean.setSecurityManager(securityManager);
         //添加Shiro拦截器
         /**
          * Shiro 内置过滤器,可以实现权限相关的拦截器
          *     anon:无需认证(登录)可以直接访问
          *     authc:必须认证才能访问
          *     user:如果使用rememberMe的功能才可以访问
          *     perms:该资源得到资源权限才可以访问
          *     role:该资源必须得到角色权限才可以访问
          */
         Map<String,String> filterMap=new LinkedHashMap<>();
         filterMap.put("/login","anon");
         //添加Shiro授权拦截器
         filterMap.put("/add","perms[添加]");
         filterMap.put("/foresee","perms[预言未来]");
         filterMap.put("/update","perms[修改]");
         filterMap.put("/delete","perms[删除]");
         filterMap.put("/*","authc");
         //跳转到登陆的页面
         shiroFilterFactoryBean.setLoginUrl("/tologin");
         //设置未授权的页面
         shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
         shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
 
         return shiroFilterFactoryBean;
     }
posted @ 2021-05-17 09:32  wode虎纹猫  阅读(337)  评论(0)    收藏  举报
Live2D