对于Shiro安全框架的使用总结

基于shiro实现认证与权限

Posted by MasterJen on November 6, 2018

Hey Shiro

A man can’t ride your back unless it is bent.–你的腰不弯,别人就不能骑在你的背上.

启动Shiro权限认证与授权,先引入依赖包

 shiro-all 里面包含了关于shiro的所有依赖。
<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-all</artifactId>
            <version>1.3.2</version>
 </dependency>

对shiro 的配置类

  @Configuration
  public class ShiroConfig {
      /**
       *  配置 SecurityManager  安全管理器 具体描述请见博客 http://sweepingmonkgo.iteye.com/blog/2115800,里面对其进行了详细的叙述
       * @param myRealm  Realm  是对权限个认证的实现类,里面进行了验证
       * @return
       */
      @Bean
      public SecurityManager securityManager(MyRealm myRealm){
          DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
          securityManager.setRealm(myRealm);
          return securityManager;
      }
  
      /**
       *   根据转数,以及盐,可以对用户进行认证
       * @param credentialsMatcher
       * @param userMapper
       * @return
       */
      @Bean
      public MyRealm myRealm(CredentialsMatcher credentialsMatcher, UserMapper userMapper){
          MyRealm myRealm = new MyRealm();
          myRealm.setCredentialsMatcher(credentialsMatcher);
          myRealm.setUserMapper(userMapper);
          return myRealm;
      }
  
      /**
       * 实现了shiro中对数据进行加盐的操作,以及转数的操作
       * @return
       */
      @Bean
      public CredentialsMatcher credentialsMatcher(){
          HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
          hashedCredentialsMatcher.setHashIterations(1024);
          hashedCredentialsMatcher.setHashAlgorithmName("MD5");
          return hashedCredentialsMatcher;
      }
  
      /**
       * 生命周期类 用于对类的生命监听。
       * @return
       */
      @Bean
      public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
          return new LifecycleBeanPostProcessor();
      }
  
      /**
       *  权限认证的 它会匹配所有的类,匹配所有加权限认证的方法,配合 spring中的aop 进行使用。
       * @param securityManager
       * @return
       */
      @Bean
      public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
          AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
          authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
          return authorizationAttributeSourceAdvisor;
      }
  
      /**
       *  过滤器注册器 用来进行对所有的请求路径进行过滤,拦截。
       * @return
       */
      @Bean
      public FilterRegistrationBean delegatingFilterProxy() {
          FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();//创建一个bean对象 相当于我们在xml文件中声明了一个filter标签
          DelegatingFilterProxy delegatingFilterProxy = new DelegatingFilterProxy("shiroFilter");
          filterRegistrationBean.setFilter(delegatingFilterProxy);//设置filer的具体类,相当于我们在xml文件中指定filter的具体类
          filterRegistrationBean.addUrlPatterns("/*");
          filterRegistrationBean.setEnabled(true);
          filterRegistrationBean.addInitParameter("targetFilterLifecycle", "true");
          return filterRegistrationBean;
      }
      /**
       * 权限类  用于权限的操作
       * @param permsMapper
       * @param securityManager
       * @return
       */
      @Bean
      public MyShiroFactoryBean shiroFilter(PermsMapper permsMapper,SecurityManager securityManager) {
          MyShiroFactoryBean myShiroFactoryBean = new MyShiroFactoryBean();
          myShiroFactoryBean.setSecurityManager(securityManager);
          myShiroFactoryBean.setPermsMapper(permsMapper);
          return myShiroFactoryBean;
      }
  }

ShiroFactory 进行扫描权限,以及对用户授权的类

public class MyShiroFactoryBean extends ShiroFilterFactoryBean {
//  进行创建 权限操作类
    private PermsMapper permsMapper;
    public void setPermsMapper(PermsMapper permsMapper) {
        this.permsMapper = permsMapper;
    }
    @PostConstruct
    public void init(){
//        设置登录
        setLoginUrl("/login.html");
//        设置权限,以及设置 登陆失败,登录成功,认证失败的界面
        Map<String, String> perms = new LinkedHashMap<>();
        setUnauthorizedUrl("/error.html");
        perms.put("/user/login", "anon");
        perms.put("/index.html", "anon");
//       在数据库中得到 所有的权限后,进行加入到 shiro 中当用户访问其路径是,判断用户是否含有其权利
        List<Map<String, String>> allPerms = permsMapper.getAllPerms();
        if(allPerms!=null){
            for (Map<String, String> entry : allPerms) {
                perms.put(entry.get("permsvalue"), "perms["+entry.get("permsvalue")+"]");
            }
        }
//        perms.put("/**","authc" );
        perms.put("/msg/savemsg", "anon");
        setFilterChainDefinitionMap(perms);//设置权限
    }
}

Realm 权限认证类

public class MyRealm extends AuthorizingRealm {
   private UserMapper userMapper;
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    //    进行权限认证的
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//        得到 域中的对象
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getSession().getAttribute("user");
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        if(user!=null){
            int user_id = user.getUser_id();
//            根据用户id  得到其具有的权利,方便权限的使用
            List<String> list =userMapper.getAllPermsByUserId(user_id);
            for (String permsvalue : list) {
//                对用户进行增加权限
                simpleAuthorizationInfo.addStringPermission(permsvalue);
            }
        }
        return simpleAuthorizationInfo;
    }
//进行  认证登录的   多种登录方式时 ,注意,约定大于代码
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = ((UsernamePasswordToken) authenticationToken).getUsername();
//        说明是手机号登录
        User user = null;
      if(username.contains("_mobile")){
          username = username.substring(0,username.lastIndexOf("_mobile"));
//         根据手机号进行查询用户
           user = userMapper.findUserByMobile(username);
      }else if(username.contains("_username")){
          username = username.substring(0,username.lastIndexOf("_username"));
//         根据用户名进行查询用户
          user = userMapper.findUserByUser_Name(username);
      }else if(username.contains("_identify")){
          username = username.substring(0,username.lastIndexOf("_identify"));
          user = userMapper.findUserByUser_Identify(username);
      }
        if(user!=null){
            SecurityUtils.getSubject().getSession().setAttribute("user", user);
//              得到 数据库中的盐
            ByteSource byteSource = ByteSource.Util.bytes(user.getSalt());
//            进行认证操作  
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,user.getPassword(),byteSource,getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}

以上便是对shiro的简单应用,小主正在研究其原理,暂未读透,哪里有瑕疵,请各位大神,多多指点。