SpringBoot+Shiro权限管理

时间:2024-11-01 14:41:26

一、为什么要了解权限框架
        权限管理框架属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则用户可以访问而且只能访问自己被授权的资源。

        目前常见的权限框架有Shiro和Spring Security,本篇文章记录springboot整合shiro,实现简单的权限控制。

二、shiro介绍
        Shiro全称是Apache Shiro,是一款灵活、强大的安全框架。方便简洁的处理身份认证、授权、加密等。

        shiro的三个组件:

        Subject 【主体】:指代当前用户【人、爬虫等】

        SecurityManager【安全管理器】:管理所有的Subject、具体安全操作的真正执行者。

        Reamls:本质是一个安全的DTO,用于进行权限、认证信息;

        通过Subject来进行认证和授权,而Subject又委托给SecurityManager; 需要给Shrio的SecurityManager注入Realm,从而让SecurityManager能得到合法的用户及其权限进行判断。

以下是一个简单的Spring Boot + Shiro权限管理示例,包含以下步骤:

1. 创建 Spring Boot 项目

可以使用 Spring Initializr(https://start.spring.io/)创建一个新的 Spring Boot 项目,添加Webthymeleaf依赖(用于示例中的简单页面展示)

2. 添加 Shiro 依赖

pom.xml文件中添加 Shiro 相关依赖

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

3. 创建实体类用户实体类(User)

public class User {
    private Long id;
    private String username;
    private String password;
    // 可以添加更多用户相关的属性,如角色列表等
    // 构造函数、Getter和Setter方法
    public User() {}
    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    // Getter和Setter方法
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

4. 创建 Shiro 配置类 

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 配置登录页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 配置未授权访问页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

        // 配置过滤器链
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 对静态资源放行
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        // 登录页面放行
        filterChainDefinitionMap.put("/login", "anon");
        // 其他请求需要认证
        filterChainDefinitionMap.put("/**", "authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

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

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

5. 创建自定义 Realm 

public class UserRealm extends AuthorizingRealm {

    // 模拟用户数据存储,可以替换为数据库查询
    private Map<String, User> userMap = new HashMap<>();

    public UserRealm() {
        userMap.put("user1", new User("user1", "password1"));
        userMap.put("admin", new User("admin", "adminpassword"));
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 这里可以根据用户角色等信息添加权限,示例简单处理
        if ("admin".equals(principals.getPrimaryPrincipal())) {
            authorizationInfo.addRole("admin");
        }
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String username = usernamePasswordToken.getUsername();
        User user = userMap.get(username);
        if (user == null) {
            throw new UnknownAccountException("用户不存在");
        }
        return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
    }
}

6. 创建控制器(Controller) 

@Controller
public class LoginController {

    @PostMapping("/login")
    public String login(String username, String password, Model model) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);
            return "redirect:/index";
        } catch (AuthenticationException e) {
            model.addAttribute("error", "用户名或密码错误");
            return "login";
        }
    }

    @GetMapping("/login")
    public String showLoginPage() {
        return "login";
    }

    @GetMapping("/unauthorized")
    public String unauthorized() {
        return "unauthorized";
    }

    @GetMapping("/index")
    public String index() {
        return "index";
    }
}

前端页面大家可以自己去实现了。 

总结:实现了一个简单的Spring Boot + Shiro权限管理系统,用户可以登录,并且根据角色(这里简单示例了普通用户和管理员)显示不同的内容。在实际应用中,需要将用户数据存储替换为数据库操作,并完善权限管理的逻辑。