当前位置: 首页 > article >正文

SpringBoot+Shiro权限管理

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

 代码实例

        引入依赖

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

        配置Shiro 

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 

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());  
    }  
}

        控制层

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;
    }

}

最后启动项目...


http://www.kler.cn/a/381006.html

相关文章:

  • 【RAG实战】Prompting vs. RAG vs. Finetuning: 如何选择LLM应用选择最佳方案
  • 如何打造用户友好的维护页面:6个创意提升WordPress网站体验
  • 深入解析 Spring Bean 配置与装配:从基础到进阶的实用指南
  • Deformable DETR:Deformable Transformers for End-to-End Object Detection论文学习
  • Go怎么做性能优化工具篇之基准测试
  • 梳理你的思路(从OOP到架构设计)_简介设计模式
  • 【机器学习】24. 聚类-层次式 Hierarchical Clustering
  • Android Studio 多工程公用module引用
  • 【专属情侣空间】不懂技术,不懂代码,你也可以拥有专属的情侣空间了
  • 各主流编程语言的常见问题点(不定时更新)
  • FrankenPHP实践
  • spring-boot(更换数据源)
  • clickhouse运维篇(二):多机器手动部署ck集群
  • 一篇文章帮你彻底解决gradle、gradle插件、jdk版本兼容性问题
  • 洗衣小程序/洗鞋小程序 洗衣店系统,洗衣系统源码
  • 面试题:JVM(六)
  • 接口/泛型
  • 界面控件DevExpress WPF中文教程:Data Grid——卡片视图概述
  • 阿里云高并发测试-Redis缓存机制
  • pdf文件预览和导出
  • 鉴源实验室·加密技术在汽车系统中的应用
  • 力扣438——找到字符串中的所有字母异位词
  • stack和queue --->容器适配器
  • Oracle Sql查询和性能优化(持续更新)
  • 掌握 Jest 中的模块模拟:提升单元测试的灵活性与可靠性
  • 【企业微信新版sdk】