完善之前的博客里的项目,本博客主要讲述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 {@Resourceprivate RoleService roleService;@Resourceprivate 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;}}
最后启动项目...