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

}

最后启动项目...

相关推荐
星河梦瑾16 分钟前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
黄名富20 分钟前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
love静思冥想21 分钟前
JMeter 使用详解
java·jmeter
言、雲24 分钟前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
TT哇31 分钟前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
机器之心43 分钟前
图学习新突破:一个统一框架连接空域和频域
人工智能·后端
Yvemil71 小时前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。1 小时前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea
计算机学长felix1 小时前
基于SpringBoot的“交流互动系统”的设计与实现(源码+数据库+文档+PPT)
spring boot·毕业设计
.生产的驴1 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven