• SpringBoot集成Shiro实现权限控制


    Shiro简介

    Apache Shiro是一个功能强大且易于使用的Java安全框架,用于执行身份验证,授权,加密和会话管理。使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移动应用程序到最大的Web和企业应用程序。

    SpringBoot常用的权限管理框架主要有Shiro和Spring Security,相对来讲,Shiro的使用要更加简单。本文主要介绍SpringBoot与Shiro的集成与初步使用。

    pom.xml引入

    <dependency>
    	<groupId>org.apache.shiro</groupId>
    	<artifactId>shiro-spring</artifactId>
    	<version>1.5.1</version>
    </dependency>
    

    LoginController

    @RestController
    public class LoginController {
    
        @RequestMapping(value = "/login", method = RequestMethod.POST)
        public Results login(String username, String password){
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            //是否记住用户
            //token.setRememberMe(true);
            
            // 执行登录方法
            // 无异常则判断为登录成功
            try{
                subject.login(token);
            }catch (UnknownAccountException e){
                return Results.failure(ResponseCode.NULL_USERNAME);
            }catch (IncorrectCredentialsException e){
                return Results.failure(ResponseCode.WRONG_PASSWORD);
            }
            return Results.success();
        }
    }
    

    Shiro中Subject代指用户对象,subject.login(token)既用户登录操作,这个方法将执行对应的认证与授权逻辑,它可能抛出两个异常:UnknownAccountException与IncorrectCredentialsException,分别为用户不存在和密码错误,无异常则判断登录成功。在这里我用自己的Results类对结果进行了封装。

    ShiroConfig

    @Configuration
    public class ShiroConfig {
    
        //创建ShiroFilterFactoryBean
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    
            //设置SecurityManager
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            
            Map<String, String> filterMap = new LinkedHashMap<>();
            //无需登录
            filterMap.put("/login", "anon");
    
            //需要登录
            filterMap.put("/user/**", "authc");
    
            //需要特定权限
            filterMap.put("/druid/stat", "roles[druid]");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
    
            //修改认证失败的跳转页面
            shiroFilterFactoryBean.setLoginUrl("/401");
            shiroFilterFactoryBean.setUnauthorizedUrl("/403");
    
            return shiroFilterFactoryBean;
        }
    
        //创建DefaultWebSecurityManager
        @Bean(name="securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联realm
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    
        // 创建Realm
        @Bean(name="userRealm")
        public UserRealm getUserRealm(){
            return new UserRealm();
        }
    }
    

    Shiro通过ShiroFilterFactoryBean来实现对URL的权限过滤,ShiroFilterFactoryBean允许接收一个Map<String, String>用于设置过滤规则,该Map的键对应需要过滤的URL,可使用通配符。该Map的值对应过滤器,常用的过滤器有:

    1. anno:无需认证
    2. authc:需要认证
    3. user:使用RememberMe功能可以直接访问
    4. perms:该资源必须得到对应资源权限才可以访问
    5. roles:该资源必须得到对应角色权限才可以访问

    我们通过传入自定义的Reaml来控制对不同用户的权限管理。

    UserRealm

    public class UserRealm extends AuthorizingRealm {
    
        @Autowired
        SysUserService sysUserService;
    
        private SysUser user;
    
        @Override
        //执行授权逻辑
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    
    	//根据用户身份授权
            if(user.getUsername().equals("zzZ")){
                info.addRole("druid");
                // info.addRoles(Permissions.adminPerms);
            }
    
            // 添加身份权限
            //info.addRole("structure:query");
            return info;
        }
    
        @Override
        //执行认证逻辑
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token1) throws AuthenticationException {
    
            UsernamePasswordToken token = (UsernamePasswordToken)token1;
    
            //查询数据库验证用户身份
            String currentUsername = token.getUsername();
            user = sysUserService.getSimpleUserByName(currentUsername);
    
            // 用户不存在
            if(user==null){return null; }
    
            String password = user.getPassword();
            return new SimpleAuthenticationInfo(user, password, "");
        }
    }
    

    编写一个自定义的UserRealm类用于执行认证与授权逻辑,这个类继承自AuthorizingRealm,重写了两个方法:

    1. doGetAuthorizationInfo: 用于执行授权逻辑
    2. doGetAuthenticationInfo: 用于执行认证逻辑,通常通过查询数据库实现。

    获取当前用户

    SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
    

    通过SecurityUtils.getSubject()方法可以获取当前用户,在Service或Controller层中可以通过当前用户身份信息实现相关逻辑。

  • 相关阅读:
    网络协议
    工具
    GPG 导入导出 Key
    文件系统 相关
    内核常见结构体定义的位置
    sysctl 命令
    git 使用技巧
    busybox 对suid的支持
    vue开发中遇到的一些问题
    http环境下解决navigator.getUserMedia` undefined 的问题
  • 原文地址:https://www.cnblogs.com/2511zzZ/p/12654179.html
Copyright © 2020-2023  润新知