SpringBoot+Shiro权限管理

完善之前的博客里的项目,本博客主要讲述Shiro的权限管理模块

代码实例

引入依赖

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

配置Shiro

java 复制代码
import org.apache.shiro.mgt.SecurityManager;  
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;  
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;  
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;  
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;  
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
  
import javax.servlet.Filter;  
import java.util.HashMap;  
import java.util.Map;  
  
@Configuration  
public class ShiroConfig {  
  
    @Bean  
    public SecurityManager securityManager(MyRealm myRealm) {  
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();  
        securityManager.setRealm(myRealm);  
        return securityManager;  
    }  
  
    @Bean  
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {  
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();  
        shiroFilterFactoryBean.setSecurityManager(securityManager);  
        shiroFilterFactoryBean.setLoginUrl("/login");  
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");  
  
        Map<String, Filter> filters = new HashMap<>();  
        // 可以添加自定义的过滤器  
        shiroFilterFactoryBean.setFilters(filters);  
  
        Map<String, String> filterChainDefinitionMap = new HashMap<>();  
        filterChainDefinitionMap.put("/login", "anon");  
        filterChainDefinitionMap.put("/**", "authc");  
  
        ShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();  
        chainDefinition.setChainDefinitionMap(filterChainDefinitionMap);  
        shiroFilterFactoryBean.setFilterChainDefinitionMap(chainDefinition.getChainDefinitionMap());  
  
        return shiroFilterFactoryBean;  
    }  
  
    @Bean  
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {  
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();  
        advisor.setSecurityManager(securityManager);  
        return advisor;  
    }  
}

自定义Realm

java 复制代码
import org.apache.shiro.authc.*;  
import org.apache.shiro.authz.AuthorizationInfo;  
import org.apache.shiro.authz.SimpleAuthorizationInfo;  
import org.apache.shiro.realm.AuthorizingRealm;  
import org.apache.shiro.subject.PrincipalCollection;  
import org.springframework.beans.factory.annotation.Autowired;  
  
public class MyRealm extends AuthorizingRealm {  
  
    @Autowired  
    private UserService userService; // 假设有一个UserService用于查询用户信息  
  
    @Override  
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {  
        String username = (String) principalCollection.getPrimaryPrincipal();  
        // 查询用户权限和角色  
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();  
        // 假设从数据库中查询到的角色和权限  
        authorizationInfo.addRole("role1");  
        authorizationInfo.addStringPermission("user:delete");  
        return authorizationInfo;  
    }  
  
    @Override  
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {  
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;  
        String username = token.getUsername();  
  
        // 查询用户信息  
        User user = userService.findByUsername(username);  
        if (user == null) {  
            throw new UnknownAccountException("用户不存在");  
        }  
  
        // 返回验证信息  
        return new SimpleAuthenticationInfo(username, user.getPassword(), getName());  
    }  
}

控制层

java 复制代码
package com.bdqn.controller;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bdqn.pojo.Right;
import com.bdqn.pojo.Role;
import com.bdqn.service.RightService;
import com.bdqn.service.RoleService;
import jakarta.annotation.Resource;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@Controller
@RequestMapping("/role")
public class RoleController {

    @Resource
    private RoleService roleService;

    @Resource
    private RightService rightService;

    /**
     * 角色列表
     */
    @RequiresPermissions("L0602")
    @RequestMapping("/list")
    public String list(Model model, String roleName, Long pageIndex) {
        // 当前要查询的页码,如果是null则设置为默认查第1页
        pageIndex = pageIndex == null ? 1 : pageIndex;

        // 分页查询用户列表
        Page page = new Page(pageIndex, 5L);
        Page<Role> rolePager = roleService.findPage(roleName, page);

        // 设置数据到作用域
        model.addAttribute("roleName", roleName); // 数据回显
        model.addAttribute("rolePager", rolePager);

        // 跳转页面
        return "role/list";
    }

    /**
     * 去添加页
     */
    @RequiresPermissions("L060201")
    @GetMapping("/add")
    public String toAdd(Model model) {
        // 查找所有权限,用于指派权限
        List<Right> rights = rightService.findAll();

        // 设置数据到作用域
        model.addAttribute("rights", rights);

        // 跳转页面
        return "role/add";
    }

    /**
     * 检查用户名是否可用({"result":"true"} 表示已存在,不可用)
     */
    @ResponseBody // REST风格,直接将数据写入响应流(对应Ajax请求)
    @GetMapping("/check")
    public String checkRoleName(String roleName, Long roleId) {
        JSONObject json = new JSONObject();
        if (roleName == null) {
            json.put("result", "error");
            return json.toJSONString();
        }
        // 判断角色名称是否可用(排除某个ID)
        Role role = roleService.getByRoleNameExceptRoleId(roleName, roleId);
        json.put("result", String.valueOf(role != null));
        return json.toJSONString();
    }

    /**
     * 跳转到修改页
     */
    @RequiresPermissions("L060204")
    @GetMapping("/edit")
    public String toEdit(Model model, Long roleId) {
        // 查找所有权限,用于指派权限
        List<Right> rights = rightService.findAll();

        // 根据ID获取角色信息
        Role role = roleService.getById(roleId);

        // 通过角色ID获取对应的权限集合
        Set<Right> roleRights = rightService.findRightByRoleId(roleId);
        role.setRights(roleRights); // 权限角色拥有的权限集合

        // 将数据设置到作用域
        model.addAttribute("rights", rights);
        model.addAttribute("role", role);

        // 跳转页面
        return "role/edit";
    }

    /**
     * 保存角色信息(权限映射关系先删除再添加)
     */
    @RequiresPermissions("L060202")
    @PostMapping("/save")
    public String save(Role role, String[] rightCodes) {
        System.out.println(role);
        // 使用Lambda表达式打印数组信息
        Arrays.stream(rightCodes).forEach(code -> System.out.print(code + ' '));
        System.out.println();
        // 保存角色及对应的权限(兼容添加和修改)
        roleService.saveRoleAndRight(role, rightCodes);

        // 重定向到列表页面
        return "redirect:/role/list";
    }

    /**
     * 删除角色
     */
    @RequiresPermissions("L060203")
    @ResponseBody
    @PostMapping("/del/{roleId}")
    public Map<String, Object> del(@PathVariable("roleId") Long roleId) {
        Map<String, Object> map = new HashMap<>();
        boolean result = false;
        map.put("result", String.valueOf(result));
        return map;
    }

}

最后启动项目...

相关推荐
Theodore_10222 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸3 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象3 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了4 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
小二·4 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic4 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
懒洋洋大魔王4 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq
武子康5 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
qq_17448285755 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
转世成为计算机大神5 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式