Spring Boot Shiro 接口权限

在现代的Web应用程序中,安全性是至关重要的。为了保护用户的数据和系统免受恶意攻击,我们需要有效的权限管理系统。Spring Boot 是一个流行的Java框架,而Shiro是一个功能强大的安全框架。结合使用Spring Boot和Shiro可以轻松实现接口权限控制。

什么是Shiro?

Apache Shiro 是一个功能强大且易于使用的Java安全框架。它提供了身份验证、授权、加密和会话管理等功能。Shiro 的核心是 Subject、SecurityManager 和 Realm。Subject 是当前用户的安全操作对象,SecurityManager 管理所有主体,并协调与 Realm 的交互。Realm 是一个组件,用于验证用户身份、授权用户以及获取用户的角色和权限信息。

Spring Boot 集成 Shiro

要在Spring Boot项目中使用Shiro,我们首先需要添加依赖:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.7.0</version>
</dependency>

然后,我们需要创建一个ShiroConfig类来配置Shiro:

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/api/**", "authc");
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
        
        return shiroFilter;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm());
        
        return securityManager;
    }

    @Bean
    public MyRealm myRealm() {
        return new MyRealm();
    }

}

在上面的代码中,我们创建了一个ShiroFilterFactoryBean实例,用于定义接口的权限规则。这里我们指定了/api/**路径需要进行身份验证。同时,我们创建了一个自定义的Realm类MyRealm,用于处理用户身份验证和授权。

编写自定义Realm类

public class MyRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        User user = (User) principals.getPrimaryPrincipal();
        authorizationInfo.addRole(user.getRole());
        authorizationInfo.addStringPermission(user.getPermission());
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        User user = userService.findByUsername(username);
        if (user != null) {
            return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
        } else {
            throw new UnknownAccountException();
        }
    }
}

MyRealm类中,我们重写了 doGetAuthorizationInfodoGetAuthenticationInfo 方法。在doGetAuthorizationInfo方法中,我们根据用户信息获取用户的角色和权限信息,然后返回给Shiro进行授权。在doGetAuthenticationInfo方法中,我们根据用户名获取用户信息进行验证。

权限控制

使用Shiro进行权限控制非常简单。在我们的Controller层中,可以使用@RequiresRoles@RequiresPermissions注解来限制访问权限。

@RestController
@RequestMapping("/api")
public class ApiController {

    @GetMapping("/admin")
    @RequiresRoles("admin")
    public String admin() {
        return "Admin Interface";
    }

    @GetMapping("/user")
    @RequiresRoles("user")
    public String user() {
        return "User Interface";
    }

    @GetMapping("/delete")
    @RequiresPermissions("delete")
    public String delete() {
        return "Delete Operation";
    }

}

在上面的代码中,我们使用@RequiresRoles注解来限制访问角色,并使用@RequiresPermissions注解来限制访问权限。只有满足对应的角色和权限要求的用户才能访问对应的接口。